簡體   English   中英

Java:輸出意外結果

[英]Java: got an unexpected output

我正在學習Java,卻得到了意外的輸出。 那是代碼:

public class Point {
    protected final int x,y;
    private final String name;

    public Point(int x,int y){
        this.x = x;
        this.y = y;
        name = makeName();
    }

    protected String makeName() {

        return "["+x+" ,"+y+"]";
    }
    public final String toString(){
        return name;
    }
}
public class ColorPoint extends Point{
    private final String color;

    public ColorPoint(int x,int y, String color){
        super(x,y);
        this.color = color;
    }

    protected String makeName(){
        return super.makeName() + ":" + color;
    }

    public static void main (String[] args){
        System.out.println(
                new ColorPoint(4,2,"viola"));
    }
}

輸出為: [4,2]:null
為什么? 不應該只是[4,2]因為變量String名稱首先在Point類的makeName()方法中初始化,然后應該變為不可變的嗎? 我錯了嗎?

在設置this.color = color之前,將調用makeName()方法。

當color變量仍然為null時,super.construtctor將調用makeName()方法。

super(x,y)調用ColorPoint類的makeName()方法,直到那時才分配顏色。

流是這樣的,

Point constructor > makeName of ColorPoint > makeName of Point

由於ColorPoint的makeName首先被調用,直到那個時候沒有分配顏色屬性值,所以它給出null

在超類的構造函數中調用makeName() 調用時尚未設置顏色,因此color的默認值為null。

要解決該問題,您必須在構造函數的末尾顯式調用makeName() 這是正確的代碼:

public ColorPoint(int x,int y, String color){
    super(x,y);
    this.color = color;
    makeName();
}
 new ColorPoint(4,2,"viola"));

在第22行調用構造函數,然后在第5行調用構造函數,在第5行調用構造函數在第27行調用覆蓋的函數make name,該函數將name設置為[4,2]:null,因為尚未初始化顏色。

final字段使用默認值(對於引用為null )初始化。 您可以使用以下代碼輕松檢查它:

class FinalTest{
    public final String value = test();

    private String test() {
        System.out.println("current state of value is '"+value+"'");
        return "foo";
    }

    public static void main(String[] args) {
        FinalTest ft = new FinalTest();
        System.out.println(ft.value);
    }
}

產生輸出:

current state of value is 'null'
foo

因此,如您所見,最終變量具有其默認值,以后可以在構造函數中對其進行一次修改。

但是,讓我們回到您的示例。 你打電話時

System.out.println(new ColorPoint(4, 2, "viola"));

您正在創建ColorPoint類的調用構造函數,然后在此實例上將調用toString 但是,讓我們仔細看看ColorPoint構造函數:

public ColorPoint(int x, int y, String color) {
    super(x, y);
    this.color = color;
}

正如您在this.color之前看到的this.color您正在調用super(x,y) ,其代碼如下所示:

public Point(int x, int y) {
    this.x = x;
    this.y = y;
    name = makeName();
}

但是在makeName(); 由於多態性( 后期綁定 ),你正在使用的代碼makeNameColorPoint類,它看起來像

protected String makeName() {
    return super.makeName() + ":" + color;
}

因此,在開始時,您將獲得super.makeName()結果,其結果為"[" + x + " ," + y + "]"但隨后您嘗試訪問的color (如您所記未初始化)

super(x, y); //<-- we are still here
this.color = color;//this wasn't invoked (yet)

因此color仍具有其默認值( null )。

這意味着name將設置為[4 ,2]:null

由於ColorPointPoint繼承toString ,看起來像

public final String toString() {
    return name;
}

您會看到以[4 ,2]:null name存儲的輸出值。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM