[英]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 由于多态性( 后期绑定 ),你正在使用的代码
makeName
从ColorPoint
类,它看起来像
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 由于
ColorPoint
从Point
继承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.