Java:获得了意想不到的输出

时间:2015-03-07 18:25:41

标签: java

我正在学习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名称首先在makeName()类的Point方法中初始化,然后应该变得不可变?我错了吗?

6 个答案:

答案 0 :(得分:2)

在设置makeName();

之前调用this.color = color方法

当颜色变量仍为makeName()时,super.construtctor会调用null方法。

答案 1 :(得分:0)

super(x,y)是ColorPoint类的调用方法makeName(),直到那时才分配颜色。

答案 2 :(得分:0)

Flow就是这样,

Point constructor > makeName of ColorPoint > makeName of Point

因为,首先调用ColorPoint的makeName,直到那时没有赋值color属性值,所以它给出null

答案 3 :(得分:0)

在超类的构造函数中调用

makeName()。 当它被调用时,颜色尚未设置,因此颜色的默认值为空。

要解决此问题,您必须在构造函数的末尾显式调用makeName()。这是正确的代码:

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

答案 4 :(得分:0)

 new ColorPoint(4,2,"viola"));

在第22行调用构造函数,该行调用第5行的构造函数 第5行的构造函数在第27行调用重写的函数make name 将名称设置为[4,2]:null,因为颜色尚未初始化。

答案 5 :(得分:0)

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

因此,当您看到final变量具有其默认值时,可以稍后在构造函数中修改一次。

但是让我们回到你的例子。当你打电话

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之前所看到的那样,您正在调用super(x,y),代码如下所示:

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

但是makeName();感谢多态(late binding),你使用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

由于ColorPointtoString继承Point,看起来像

public final String toString() {
    return name;
}

您将name中存储的输出值视为[4 ,2]:null