Java類謎題51:那個點是什么

字號:

下面這個程序有兩個不可變的值類(value class),值類即其實例表示值的類。第一個類用整數(shù)坐標來表示平面上的一個點,第二個類在此基礎(chǔ)上添加了一點顏色。主程序?qū)?chuàng)建和打印第二個類的一個實例。那么,下面的程序?qū)⒋蛴〕鍪裁茨兀?BR>    class Point {
     protected final int x, y;
     private final String name; // Cached at construction time
     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;
     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, "purple"));
     }
    }
    main方法創(chuàng)建并打印了一個ColorPoint實例。println方法調(diào)用了該ColorPoint實例的toString方法,這個方法是在Point中定義的。toString方法將直接返回name域的值,這個值是通過調(diào)用makeName方法在Point的構(gòu)造器中被初始化的。對于一個Point實例來說,makeName方法將返回[x,y]形式的字符串。對于一個ColorPoint實例來說,makeName方法被覆寫為返回[x,y]:color形式的字符串。在本例中,x是4,y是2,color的purple,因此程序?qū)⒋蛴4,2]:purple,對嗎?不,如果你運行該程序,就會發(fā)現(xiàn)它打印的是[4,2]:null。這個程序出什么問題了呢?
    這個程序遭遇了實例初始化順序這一問題。要理解該程序,我們就需要詳細跟蹤該程序的執(zhí)行過程。下面是該程序注釋過的版本的列表,用來引導我們了解其執(zhí)行順序:
    class Point {
     protected final int x, y;
     private final String name; // Cached at construction time
     Point(int x, int y) {
     this.x = x;
     this.y = y;
     name = makeName(); // 3. Invoke subclass method
     }
     protected String makeName() {
     return "[" + x + "," + y + "]";
     }
     public final String toString() {
     return name;
     }
    }
    public class ColorPoint extends Point {
     private final String color;
     ColorPoint(int x, int y, String color) {
     super(x, y); // 2. Chain to Point constructor
     this.color = color; // 5. Initialize blank final-Too late
     }