开发者社区> 问答> 正文

java继承中为什么向上转型后无法运行子类中特有的方法?

class Person { 
 public String toString(){
    return "I'm a person."; 
 } 
 public void eat(){} 
 public void speak(){} 
    
 } 

 class Boy extends Person{ 
 public String toString(){ 
    return "I'm a boy"; 
     } 
 public void speak(){} 
 public void fight(){} 
 } 

 class Girl extends Person{ 
 public String toString(){ 
    return "I'm a girl"; 
     } 
 public void speak(){} 
 public void sing(){} 
 }
//最后这么用的话,
Person girl = new Girl(); 
girl.speak(); 

girl引用变量指向堆中的 Girl对象,所以运行的时候知道当前对象是Girl对象,找Girl的方法表,找到后执行。这对于speak方法来说是行得通的。但是如果这样呢:girl.sing();去Girl方法表找到sing方法,然后执行。
实际情况大家都知道有错误,编译不通过。当发生向上转型的时候,栈和堆中分别发生了什么?

展开
收起
蛮大人123 2016-03-11 15:19:38 2647 0
1 条回答
写回答
取消 提交回答
  • 我说我不帅他们就打我,还说我虚伪

    是变量的声明类型决定了它能调用哪些方法,而不是它指向的堆中的对象的实际类型。
    像你这样:

    Person girl = new Girl();
    girl.speak(); 

    girl的声明类型是Person,而Person并没有speak这个方法,所以会报错。注意是编译器报的编译期的错误,编译器是不管你那个girl执行的类型到底是什么。
    运行期,虚拟机当然会知道girl执行的堆中对象是Girl类型。
    编译器为什么要根据变量的声明类型来决定能不能调用某个方法?其中一个原因就是,编译期间可能根本不知道这个变量在运行期绑定的到底是什么类型的对象。举个例子:
    Person p = Math. random() > 0.5 ? new Girl() : Boy();
    这个例子中的p不到运行时根本没法确定它绑定的对象的真实类型。

    2019-07-17 18:59:22
    赞同 展开评论 打赏
问答排行榜
最热
最新

相关电子书

更多
Spring Cloud Alibaba - 重新定义 Java Cloud-Native 立即下载
The Reactive Cloud Native Arch 立即下载
JAVA开发手册1.5.0 立即下载