Java 确定实际调用的覆盖方法
例如,当子类对象被强制转换为其超类时Java 确定实际调用的覆盖方法,java,Java,例如,当子类对象被强制转换为其超类时 Superclass obj = new Subclass(); 并且定义了类 public class Superclass{ public void thisMethod(){ System.out.println("Superclass version was executed"); } 及 当调用obj.thisMethod()时,我得到的子类版本被调用为输出,这显然意味着调用了子类中定义的该方法的版本(原始超类对象无法“
Superclass obj = new Subclass();
并且定义了类
public class Superclass{
public void thisMethod(){
System.out.println("Superclass version was executed");
}
及
当调用obj.thisMethod()
时,我得到的子类版本被调用为输出,这显然意味着调用了子类中定义的该方法的版本(原始超类对象无法“执行”的版本),尽管声明的类型是超类,是吗?
因此,即使子类方法是在obj上执行的,
调用obj.newMethod()
时,我得到一个编译错误
基本上,为什么在通过超类对象调用的子类中定义了thisMethod()
的版本?我知道,obj
的实际类型仍然是子类,因此自然应该调用新版本,但是,我是否应该能够调用obj.newMethod()
谢谢你的解释(:
编辑:表示在标题中被覆盖*
基本上,为什么在通过超类对象obj调用的子类中定义thisMethod()的版本
因为这基本上是继承点-它允许实现重写,而调用代码不需要知道正在使用哪个实现。以InputStream
为例-您可以使用InputStream
进行编码,然后无论是否传递了FileInputStream
,一个ByteArrayInputStream
等。在抽象类或接口的情况下,您可以调用编译时类型中没有任何实现的方法,但可以保证在执行时使用的具体对象类型中会有一个实现
我知道obj的实际类型仍然是子类,因此自然地,应该调用新版本,但是,我是否应该能够调用obj.newMethod()
不,因为obj
的编译时类型是Superclass
。区分变量的编译时类型(决定哪些方法等可用)和变量值引用的对象的执行时类型(决定哪些方法实现可用)非常重要实际上是这样的
这只是一个非常简短的描述-您应该阅读Java好书中关于继承的一章以了解更多详细信息。超类obj=new Subclass()在这个定义中,您只能在超类中使用公开的方法。在您的声明中,当您将调用任何方法时,实际上指向子类对象,它将调用子类实现。理论上,obj
是一个指向子类
对象的超类
引用
因为编译器obj
只是一个Superclass
,所以所有Superclass
的方法都可以调用,例如thisMethod
,编译器不知道对象的类型,只知道引用的类型,因此编译器将拒绝newMethod
,因为它无法证明此方法存在。
但是在运行时,对象的类型用于分派方法,而不是引用的类型,因此thisMethod
将解析为子类的版本
现在,如果我们知道运行时对象的类型是Subclass
,我们想告诉编译器这一点,我们进行一次转换:
Subclass subobj = (Subclass) obj;
在编译器知道subobj
属于Subclass
类型并将接受调用newMethod
之后,cast只是编译器的一个信息,不会更改对象obj
中的任何内容,如果obj
不是子类,则前面的语句将抛出ClassCastExcep在运行时执行操作
Subclass subobj = (Subclass) obj;