Javainheritance字段

我无法理解以下输出。

我不知道为什么输出是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(ai); } } 

为什么这样工作..请解释。

首先,看隐藏字段 (重点添加)

在类中,与超类中的字段具有相同名称的字段会隐藏超类的字段 ,即使它们的类型不同

换句话说,这不是“inheritance”,因为你实际上是将Ai隐藏在Bi ,并且你正在使用A的引用对象,所以你得到它的字段。 如果你做了B b = new B() ,你会看到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 

在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()); } } 

多态性不适用于Java中的字段 。评估变量决策是在编译时进行的,因此始终要访问基类变量。

因为您定义了2个变量:一个在子类B ,另一个在超类A具有相同的名称。

 A a = new B(); ai; // refers to Ai 

如果你将A转换为B ,它将访问Bi

 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(ai); // will print 20 } 

成员变量i已在class A定义。

为了达到您的目的,请更改class B ,如下所示:

 class B extends A { public B() { i = 20; } }