简体   繁体   English

Java:输出意外结果

[英]Java: got an unexpected output

I'am learning Java and I got an unexpected output. 我正在学习Java,却得到了意外的输出。 That's the code: 那是代码:

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"));
    }
}

The output is: [4,2]:null . 输出为: [4,2]:null
Why? 为什么? Shouldn't it be just [4,2] because the variable String name is initialized first in makeName() method of the Point class and then should become unmutable? 不应该只是[4,2]因为变量String名称首先在Point类的makeName()方法中初始化,然后应该变为不可变的吗? Am I wrong? 我错了吗?

the makeName() method is called before you set this.color = color ; 在设置this.color = color之前,将调用makeName()方法。

The makeName() method is called by your super.construtctor when the color variable is still null . 当color变量仍然为null时,super.construtctor将调用makeName()方法。

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

Flow is like this, 流是这样的,

Point constructor > makeName of ColorPoint > makeName of Point

since, makeName of ColorPoint is called first, till that time color property value was not assigned, so its giving null 由于ColorPoint的makeName首先被调用,直到那个时候没有分配颜色属性值,所以它给出null

makeName() is called in the constructor of the superclass. 在超类的构造函数中调用makeName() When it is called color is not yet set so the default value of color is null. 调用时尚未设置颜色,因此color的默认值为null。

To solve the problem you have to explicitly call makeName() at the end of constructor. 要解决该问题,您必须在构造函数的末尾显式调用makeName() Here is the correct code: 这是正确的代码:

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 fields are initialized with default values (which for references is null ). final字段使用默认值(对于引用为null )初始化。 You can easily check it with this code: 您可以使用以下代码轻松检查它:

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);
    }
}

which produces output: 产生输出:

current state of value is 'null'
foo

So as you see final variable has its default value which can be later modified in constructor once. 因此,如您所见,最终变量具有其默认值,以后可以在构造函数中对其进行一次修改。

But lets get back to your example. 但是,让我们回到您的示例。 When you call 你打电话时

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

you are creating invoking constructor of ColorPoint class, and then on this instance toString will be called. 您正在创建ColorPoint类的调用构造函数,然后在此实例上将调用toString But lets take a closer look at ColorPoint constructor: 但是,让我们仔细看看ColorPoint构造函数:

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

As you see before this.color will be set you are invoking super(x,y) which code looks like this: 正如您在this.color之前看到的this.color您正在调用super(x,y) ,其代码如下所示:

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

But here in makeName(); 但是在makeName(); thanks to polymorphism ( late binding ) you are using code of makeName from ColorPoint class which looks like 由于多态性( 后期绑定 ),你正在使用的代码makeNameColorPoint类,它看起来像

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

So at start you will get result of super.makeName() which is "[" + x + " ," + y + "]" but then you are trying to access color which as you remember is not initialized with because 因此,在开始时,您将获得super.makeName()结果,其结果为"[" + x + " ," + y + "]"但随后您尝试访问的color (如您所记未初始化)

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

so color still has its default value ( null ). 因此color仍具有其默认值( null )。

This means that name will be set to [4 ,2]:null . 这意味着name将设置为[4 ,2]:null

Since ColorPoint inherits toString from Point which looks like 由于ColorPointPoint继承toString ,看起来像

public final String toString() {
    return name;
}

you see as output value stored in name which is [4 ,2]:null . 您会看到以[4 ,2]:null name存储的输出值。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM