public class CovariantTest {
public A getObj() {
return new A();
}
public static void main(String[] args) {
CovariantTest c = new SubCovariantTest();
System.out.println(c.getObj().x);
}
}
class SubCovariantTest extends CovariantTest {
public B getObj() {
return new B();
}
}
class A {
int x = 5;
}
class B extends A {
int x = 6;
}
Run Code Online (Sandbox Code Playgroud)
上面的代码在编译和运行时打印5.它使用过度返回方法的协变返回.
为什么它会打印5而不是6,因为它在SubCovariantTest类中执行overRidden方法getObj.
有人可以对此有所了解.谢谢.
Law*_*Dol 15
这是因为在Java成员变量不覆盖时,它们会影响(与方法不同).A和B都有变量x.由于c被声明为CovarientTest类型,因此getObj()的返回隐式为A,而不是B,因此得到A的x,而不是B的x.
Spo*_*ike 11
Java 不会覆盖字段(aka.属性或成员变量).相反,他们互相遮蔽.如果您通过调试器运行程序,您将x在任何类型的对象中找到两个变量B.
这是对正在发生的事情的解释.程序首先检索隐式类型的东西,A然后调用x假定来自的东西A.尽管它显然是一个子类型,但在您的示例中,类型的对象B是通过创建的SubCovariantTest,它仍然假设您在getObj()中返回隐式类型为A的内容.由于Java无法覆盖字段,因此测试将调用A.x而不是B.x.
CovariantTest c = new SubCovariantTest();
// c is assumed the type of CovariantTest as it is
// implicitly declared
System.out.println(c.getObj().x);
// In this method chain the following happens:
// c.getObj() will return object of type B
// BUT will assume it is an A
// c.getObj().x will return the x from A
// since in this context the compiler assumes
// it is an A and make the call to A.x
Run Code Online (Sandbox Code Playgroud)
它似乎是一个令人难以置信的陷阱,因为方法总是在Java中被覆盖(与C++和C#相比,它们不是).您通常不会遇到此问题,因为Java代码约定会告诉您永远不要直接访问字段.而是确保始终通过访问器方法(即getter)访问字段:
class A {
private int x = 5;
public int getX() { // <-- This is a typical accessor method
return x;
}
}
class B extends A {
private int x = 6;
@override
public int getX() {
// will be called instead even though B is implied to be A
// @override is optional because methods in Java are always virtual
// thus are always overridden
return x;
}
}
Run Code Online (Sandbox Code Playgroud)
使此工作的代码如下:
c.getObj().getX();
// Will now call getX() in B and return the x that is defined in B's context.
Run Code Online (Sandbox Code Playgroud)
小智 10
将上面的A和B替换为:
class A {
public int getX() { return 5; }
}
class B extends A {
public int getX() { return 6; }
}
Run Code Online (Sandbox Code Playgroud)
这可能会回答你关于错误的问题;-)
在对象中有两个名为x的字段,一个来自A类,一个来自B类,它们隐藏了A中的字段.由于c的声明,字段x引用的是A中的字段.
在实践中,这不是一个问题,因为它是非常糟糕的风格
隐藏子类中的字段,
直接访问字段而不是通过方法.
| 归档时间: |
|
| 查看次数: |
885 次 |
| 最近记录: |