SER*_*ich 13 java variables polymorphism constructor initialization
假设您有以下代码
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);
}
}
Run Code Online (Sandbox Code Playgroud)
这将打印0 2
现在,如果删除标有"此行"的行,代码将打印4 4
A a = new B();将调用类A,将i初始化为4,调用构造函数,
将控制权交给print()方法class B,最后打印4.
a.print()将调用print()类B中的方法,因为这些方法将在运行时绑定,这也将使用在类A,4中定义的值.
(当然,如果我的推理有任何错误,请告诉我)
为什么如果你插入代码,第一部分(创建对象)将突然打印0而不是4?为什么不将变量初始化为i = 4,而是指定默认值?
它是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);
}
}
Run Code Online (Sandbox Code Playgroud)
所以,当你原来的时候main(),你打电话A a = new B();,它正在构建一个B,为此发生这种情况:
A::i并且B::i都是默认值0A::i 设置为4print()叫做.由于后期绑定,它必然会B::print()B::print()正在尝试打印出来B::i,这仍然是0B::i 设置为2然后当你打电话给a.print()你的时候main(),B::print()打印出来的是有限的B::i(此刻是2).
因此你看到的结果
新对象中的所有实例变量(包括在超类中声明的变量)都初始化为其默认值 - JLS 12.5
因此,您的变量B::i将初始化为0. B中的构造函数将如下所示:
B() {
super();
i = 2;
}
Run Code Online (Sandbox Code Playgroud)
所以当你打电话
A a = new B();
Run Code Online (Sandbox Code Playgroud)
A中的构造函数将调用printB中的方法,该方法将打印i类B中的方法,即0.
在你的情况下,B类,"i"的声明在A中隐藏了"i"的声明,而在子类中对"i"的所有引用都指的是Bi而不是Ai
所以你在Ai中看到的是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);
}
}
Run Code Online (Sandbox Code Playgroud)
输出继电器:
a.i is 4
b.i is 2
Run Code Online (Sandbox Code Playgroud)