我正在准备 SCJP(最近被 Oracle 更名为 OCPJP),我在模拟考试中做错的一个特定问题让我感到困惑,答案描述并没有足够清楚地解释事情。
这是问题:
class A
{
int x = 5;
}
class B extends A
{
int x = 6;
}
public class CovariantTest
{
public A getObject()
{
return new A();
}
public static void main(String[]args)
{
CovariantTest c1 = new SubCovariantTest();
System.out.println(c1.getObject().x);
}
}
class SubCovariantTest extends CovariantTest
{
public B getObject()
{
return new B();
}
}
答案是5
,但我选择了6
。
我知道重写适用于运行时的方法,而不适用于变量,但我的想法解释 println
的方式是:
- 在 c1 上调用 getObject
- c1 实际上是一个
SubCovariantTest
对象,并且有一个有效的覆盖 对于getObject()
,所以使用覆盖的方法 - 重写返回 B,所以从 B 中获取 x,即 6
这是 JVM 忽略 getObject()
部分的情况,并且总是从 c1
中获取 x
因为变量在编译时关联时间?
最佳答案
虽然对 SubCovariantTest 的覆盖是正确的,但由于变量 c1 的声明方式,答案是 5。它被声明为 CovariantTest 而不是 SubCovariantTest。
运行 c1.getObject().x 时,它不知道它是一个 SubCovariantTest(未使用转换)。这就是为什么从 CovariantTest 返回 5 而不是从 SubCovariantTest 返回 6 的原因。
如果你改变
System.out.println(c1.getObject().x);
到
System.out.println(((SubCovariantTest) c1).getObject().x);
如你所料,你会得到 6。
编辑:正如评论中所指出的
“字段在 Java 中不是多态的。只有方法是。子类中的 x 隐藏了基类中的 x。它不会覆盖它。” (感谢 JB Nizet)
关于java - 关于覆盖变量的地方有点困惑,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12589274/