kingxip 2009-06-13 21:10
浏览 191
已采纳

构造器中的多态

[code="java"]
public class Parent {
private int eatId=0;
public Parent() {
System.out.println("parent is creating");
eat();
}
public void eat() {
System.out.println("==parent is eating "+eatId);
}
public static void main(String[] args) {
Parent p=new Son();
}
}

class Son extends Parent {
private int eatId=1;
public Son() {
System.out.println("son is creating");
eat();
}
public void eat() {
System.out.println("==son is eating "+eatId);
}
}
[/code]
如上代码,输出结果:
parent is creating //1
==son is eating 0 //2
son is creating //3
==son is eating 1 //4


疑惑的是,
1)输出中2 3行,为什么son在构造之前(按我的理解就是还没有生成)就可以调用它的eat方法了,如果可以调用这个时候的eatId是谁的,为什么?从结果看来是parent的 可是在parent中eatId是似有的啊?
2)eatId作为私有变量,parent中和son中有没有关系,他们存不存在重载的情况?

自己有点乱,请高人解释一下啊
[b]问题补充:[/b]
但是son 在还没有具体创建成功的时候 怎么能够调用他的方法呢?
RednaxelaFX 说的对,那个0不是表示parent 时表示jvm默认的初始赋值

  • 写回答

3条回答 默认 最新

  • rednaxelafx 2009-06-13 23:25
    关注

    楼主可能没理解的是,在Java中,一个类的所有方法的代码都是编译时就确定好的。一个类经由JVM加载后,其中所有的方法在任何时候都可以被调用。成员方法比较特别,因为它们有一个隐藏参数(this),而这个参数就是对象实例。

    JVM构造对象实例是先分配空间(此时实例的所有状态介被默认初始化,也就是数字类型初始化为0,布尔类型初始化为false,引用类型初始化为null),再调用构造器。其中,构造器总是会通过基类的构造器来初始化实例中由基类的定义数据部分;即使用户写的构造器里没有显式调用基类的构造器,只要基类有默认构造器,就会在派生类构造器中第一行代码之前先调用基类的默认构造器;否则用户必须提供显式的对基类构造器的调用。
    也就是说,调用构造器的时候,对象实例已经存在了,虽然其中的值还没有根据用户代码进行初始化。此时调用成员方法自然是可以的,只是状态很可能还没达到用户希望的初始状态而已。

    例如在Java里写new Object(),编译为JVM字节码之后是:
    [code="JVM bytecode"]new java/lang/Object // 创建实例
    dup // 这个不用管,跟JVM的栈模型相关
    invokespecial java/lang/Object.:()V // 调用构造器[/code]
    观察到创建对象实例与调用构造器的动作是分开的。

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(2条)

报告相同问题?

悬赏问题

  • ¥15 用stata实现聚类的代码
  • ¥15 请问paddlehub能支持移动端开发吗?在Android studio上该如何部署?
  • ¥170 如图所示配置eNSP
  • ¥20 docker里部署springboot项目,访问不到扬声器
  • ¥15 netty整合springboot之后自动重连失效
  • ¥15 悬赏!微信开发者工具报错,求帮改
  • ¥20 wireshark抓不到vlan
  • ¥20 关于#stm32#的问题:需要指导自动酸碱滴定仪的原理图程序代码及仿真
  • ¥20 设计一款异域新娘的视频相亲软件需要哪些技术支持
  • ¥15 stata安慰剂检验作图但是真实值不出现在图上