假设我定义了两个类,Super
和Sub
,而Sub
是Super
的子类:
public class Super {}
public class Sub extends Super {}
我知道执行以下操作是合法的:
Super s = new Sub();
我的问题是,编译器认为s
中的引用是什么?它是否认为它只是Super
类型的引用,或者它是否知道它实际上是类型Sub
的引用。我已经四处寻找与此类似的问题的答案,但是没有发现任何真正确定的问题。谢谢!
答案 0 :(得分:1)
您要问的是s
的运行时类型与s
的编译时类型。在编译时,它被认为是Super
,因为它是在代码中声明的方式。但是在运行时,它被视为Sub
。
答案 1 :(得分:1)
要回答你的问题,我们可以添加一些类的方法: -
public class Super {
public void superMethod();
}
public class Sub extends Super {
public void childMethod();
}
如果现在我们尝试编译以下这些行: -
Super s = new Sub();
s.superMethod();
s.childMethod();
在上面的代码最后一行中,不会编译,因为childMethod不存在于Class super中,而只存在于Sub中。因此,编译器没有编译,因为它引用s作为Sub。
答案 2 :(得分:1)
编译器可能会知道"出于警告消息的目的,你有Sub
的实例(因此,它可能会警告你,如果它看到你将它转换为其他类型,或者不必要地检查它是否为空),但是就其而言该语言允许和禁止,变量只有Super
类型。
(但在运行时,当然,Java虚拟机将知道该实例具有运行时类型Sub
。)
答案 3 :(得分:1)
编译器只将其视为Super
。
考虑:
public class Super {}
public class Sub extends Super {
void f() {}
}
考虑编译以下代码:
Super s = new Sub();
if (s instanceof Sub) {
s.f(); // ERROR: will not compile!
}
即使编译器可以判断正在检查s
的类型,并且if
块中s
必须是Sub
类型(或某些后代) ,如果没有明确的演员,它仍然不会将s
视为Sub
。
Super s = new Sub();
if (s instanceof Sub) {
((Sub)s).f(); // Now this compiles.
}