假设您有以下代码
class A {
int i = 4;
A() {
print();
}
void print () {
System.out.println("A");
}
}
class B extends A {
int i = 2; //"this line"
public static void main(String[] args){
A a = new B();
a.print();
}
void print () {
System.out.println(i);
}
}这将打印0 2
现在,如果删除标记为“本行”的行,代码将打印4 4。
A a = new B();将调用A类,将i初始化为4,调用构造函数,
给出了print()方法在class B中的控制权,并最终打印出4条。
a.print()将调用B类中的print()方法,因为这些方法将在运行时绑定,这也将使用在类A,4中定义的值。
(当然,如果我的推理有任何错误,请告诉我)
为什么如果插入代码,第一部分(创建对象)会突然打印0而不是4?为什么它不将变量初始化为i=4,而是指定默认值?
发布于 2016-09-26 03:29:33
它是Java中几种行为的组合。
我将简单地回顾一下您代码中发生的事情,看看您是否理解。
您的代码在概念上看起来如下(跳过main()):
class A {
int i = 0; // default value
A() {
A::i = 4; // originally in initialization statement
print();
}
void print () {
System.out.println("A");
}
}
class B extends A {
int i = 0; // Remember this shadows A::i
public B() {
super();
B::i = 2;
}
void print () {
System.out.println(i);
}
}因此,当您在原始main()中调用A a = new B();时,它正在构造一个B,这种情况会发生:
A::i和B::i都是默认值0A::i设置为4print()被称为。由于后期绑定,它被绑定到B::print()。B::print()正在尝试打印B::i,它仍然是0
B::i设置为2然后,当您在您的a.print()中调用main()时,它将被绑定到正在打印B::i (此时为2)的B::print()上。
因此你所看到的结果
发布于 2016-09-26 02:59:04
新对象中的所有实例变量,包括在超类中声明的变量,都被初始化为它们的默认值- JLS 12.5。
因此,变量B::i将初始化为0。B中的构造函数类似于:
B() {
super();
i = 2;
}所以当你打电话
A a = new B();A中的构造函数将调用B中的print方法,该方法将打印B类中的i,即0。
发布于 2016-09-26 03:01:02
在你的B类中,"i“的声明隐藏了A中"i”的声明,而在子类中所有对"i“的引用都是指B.i而不是A.i。
所以你在A.i中看到的是java中任何int属性的默认值,它是零。
不能在子类中重写Java实例变量。
你想试试这个以求更多的澄清。
class B extends A {
int i = 2; //"this line"
public static void main(String[] args){
B b = new B();
A a = b;
System.out.println("a.i is " + a.i);
System.out.println("b.i is " + b.i);
}
void print () {
System.out.println(i);
}
}输出:
a.i is 4
b.i is 2https://stackoverflow.com/questions/39693922
复制相似问题