我无法理解以下输出。
我不知道为什么输出为10,我认为行A a = new B()
创建了一个B类的新实例,我认为结果应该是20
class A {
int i = 10;
}
class B extends A {
int i = 20;
}
public class MainClass {
public static void main(String[] args) {
A a = new B();
System.out.println(a.i);
}
}
为什么会这样......请解释一下。
答案 0 :(得分:33)
首先,请参阅Hiding Fields(强调添加)
在一个类中,与超类中的字段同名的字段会隐藏超类的字段,即使它们的类型不同
换句话说,这不是" t"继承"因为您实际隐藏A
i
B
i
后面的A
,并且您正在使用{{B b = new B()
的引用对象1}},所以你得到它的领域。如果您执行了20
,则会按预期看到class A {
public int get() {
return 10;
}
}
class B extends A {
@Override
public int get() {
return 20;
}
}
。
如果您希望使用真正的覆盖,请尝试使用方法。
A a = new B();
System.out.print(a.get()); // 20
见
class A {
int i = 10;
}
class B extends A {
int i = 20;
@Override
public String toString() {
return String.format("super: %d; this: %d", super.i, this.i);
}
}
如果您真的想同时查看两者,请参阅此示例。
A a = new B();
System.out.print(a); // super: 10; this: 20
并且
User.unscoped.all
答案 1 :(得分:19)
在java中,您无法覆盖实例变量。您获得的输出是预期的。在Java中,您只能覆盖实例方法而不是实例变量。
如果你想要20作为输出,你可以在这些实例变量上使用getter方法。
class A {
int i = 10;
int getI() {
return i;
}
}
class B extends A {
int i = 20;
int getI() {
return i;
}
}
public class MainClass {
public static void main(String[] args) {
A a = new B();
System.out.println(a.getI());
}
}
答案 2 :(得分:12)
多态性不适用于Java中的字段。评估变量决策是在编译时进行的,因此始终会访问基类变量。
答案 3 :(得分:4)
因为你定义了两个变量:一个在子类B
中,一个在超类A
中具有相同的名称。
A a = new B();
a.i; // refers to A.i
如果您将A
投射到B
,则会访问B.i
:
System.out.println(((B)a).i);
我认为您需要使用1个变量:
class A {
int i;
public A() {
i = 10;
}
}
class B extends A {
public B() {
i = 20;
}
}
public class MainClass {
public static void main(String[] args) {
A a = new B();
System.out.println(a.i); // will print 20
}
答案 4 :(得分:1)
成员变量i
已在class A
中定义。
为了达到您的目的,请更改class B
,如下所示:
class B extends A {
public B() {
i = 20;
}
}