我正在阅读一本Java教科书并遇到了疑问。 可以为超类的引用变量分配对从该超类派生的任何子类的对象的引用。但是,当将子类对象的引用分配给超类引用变量时,您将只能访问超类定义的对象的那些部分。 例如:
class X {
int a;
X(int i) {
a = i;
}
}
class Y extends X {
int b;
Y(int i, int j) {
super(j);
b = i;
}
}
class SupSubRef {
public static void main(String args[]) {
X x = new X(10);
X x2;
Y y = new Y(5, 6);
x2 = x; // OK, both of same type
System.out.println("x2.a: " + x2.a);
x2 = y; // still Ok because Y is derived from X
System.out.println("x2.a: " + x2.a);
// X references know only about X members
x2.a = 19; // OK
// x2.b = 27; // Error, X doesn't have a b member
}
}
因此,在上面的例子中,x2(超类类型的变量)可以引用派生类的对象,它不能访问子类特定成员。但是,在关于方法重写的讨论中,显示了超类引用变量对重写方法的调用可以解析为子类方法。但是子类方法没有在超类中定义,所以这不是一个矛盾,超类引用变量如何能够访问子类特定的方法?例如:
class Sup {
void who() {
System.out.println("who() in Sup");
}
}
class Sub1 extends Sup {
void who() {
System.out.println("who() in Sub1");
}
}
class Sub2 extends Sup {
void who() {
System.out.println("who() in Sub2");
}
}
class DynDispDemo {
public static void main(String args[]) {
Sup superOb = new Sup();
Sub1 subOb1 = new Sub1();
Sub2 subOb2 = new Sub2();
Sup supRef;
supRef = superOb;
supRef.who();
supRef = subOb1;
supRef.who();
supRef = subOb2;
supRef.who();
}
}
程序的输出如下所示:
who() in Sup
who() in Sub1
who() in Sub2
那么supRef如何能够访问子类对象中的who方法呢?
答案 0 :(得分:1)
当教科书说您无法使用x2
访问特定于子类的成员时,这意味着您无法在编译时访问它们。
到编译器。 x2
的类型为X
(虽然它在运行时中的类型为Y
),因此当编译器看到您尝试访问{{1}中定义的内容时它突出并说“Y
中没有定义。你不能这样做!”
但是,我们都知道在运行时,X
存储对x2
对象的引用。在运行时,您可以确实使用Y
访问Y
中定义的成员。你可以用反射证明这一点。
在运行时,x2
的类型为x2
,因此显然会调用Y
的实现。