[英]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();
由於多態性( 后期綁定 ),你正在使用的代碼makeName
從ColorPoint
類,它看起來像
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
。
由於ColorPoint
從Point
繼承toString
,看起來像
public final String toString() {
return name;
}
您會看到以[4 ,2]:null
name
存儲的輸出值。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.