超类引用变量所包含的引用类型是什么?

时间:2016-12-15 17:55:56

标签: java oop inheritance

假设我定义了两个类,SuperSub,而SubSuper的子类:

public class Super {}
public class Sub extends Super {}

我知道执行以下操作是合法的:

Super s = new Sub();

我的问题是,编译器认为s中的引用是什么?它是否认为它只是Super类型的引用,或者它是否知道它实际上是类型Sub的引用。我已经四处寻找与此类似的问题的答案,但是没有发现任何真正确定的问题。谢谢!

4 个答案:

答案 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.
}