我知道变量没有多态性。如果我们执行新的Subclass()。x,则在运行时将打印值20。 但是这里
Parent p = new Child();
p.getObject();
子类的getObject()将被调用,因为子类的getObject将覆盖超类的getObject()。因此子类方法getObject()返回新的Child(),因此打印的值应该是Child.x的值。但是输出是10.为什么x的值是超类的值?我知道有些帖子与此有关但不完全在任何地方都有解释。请帮忙。
class MainClass {
public static void main(String[] args) {
Parent p = new Child();
System.out.println(p.getObject().x);
}
}
class Parent {
int x = 10;
public Parent getObject() {
return new Parent();
}
}
class Child extends Parent {
int x = 20;
public Child getObject() {
return new Child();
}
}
答案 0 :(得分:0)
您正在访问类x
中的变量Parent
,因为p.getObject()
的声明类型是Parent
。
答案 1 :(得分:0)
完全是关于Java中的内存分配
拥有Parent p = new Child();
意味着您在堆上创建了一个类Child的对象,并且对它的引用命名为p,但是这个引用意味着对类Parent的对象进行操作。
所以你要分配一个Child类型的对象,但是引用是用Parent运行的。
这意味着,引用将无法看到Child的x属性。它只会看到Parent属性。
答案 2 :(得分:0)
您所做的是阴影。如果使用已在可达范围内定义的名称声明变量,则该变量将隐藏(隐藏)已定义的变量。如果要使用外部作用域中的变量,则必须编写该变量的绝对路径或使用对该变量唯一的访问器。
public class A {
int a;
public A(int a) {
System.out.println(a); // arg "a" has shadowed class field
System.out.println(this.a);
// that's why we are using this assignment:
this.a = a;
}
}
你的例子也是如此。 child.x
已隐藏parent.x
字段。如果对象引用是Child
类型i。即Child c = new Child();
,默认情况下,将使用最近的可到达变量x
(Child.x
)。如果您的对象引用是Parent
类型i。即Parent p = new Parent();
,然后将再次使用最近的可到达x
(Parent.x
)。这同样适用于Parent p = new Child();
,因为p
为new Child
,但已提升为Parent
类型,因此p.x
将显示Parent.x
值。
您必须记住,多态不适用于类字段。除非它包含在某个getter中,否则不能覆盖字段值。
因此,如果您需要覆盖显示的值,则必须将此值包装在某个getter中,该getter将被Child
类覆盖:
public class Test {
public static void main(String[] args) {
Parent p = new Child();
System.out.println(p.getObject().getValue()); // 20
System.out.println(p.getValue()); // 20
}
static class Parent {
int x = 10;
public int getValue() {return x;}
public Parent getObject() {return new Parent();}
}
static class Child extends Parent {
int x = 20;
@Override
public int getValue() {return x;} // return Child.x
@Override
public Child getObject() {return new Child();}
}
}