[英]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.