class Base{
int i=1;
public void amethod(){
System.out.println(“Base.amethod()”);
}
Base(){
amethod();    //调试时发现amethod()方法的实现代码是子类重写的代码?子类重写父类的方法,在父类指向子类时,父类的方法会变重写掉吗?
}
}
public class Descend extends Base{
int i=-1;
public static void main(String[] args){
Base b=new Descend();    //父类指向子类,那么在实例化时,应该是先去运行父类的构造方法,那么运行是应该是父类的amethod()方法呀,可是程序怎么是运行子类重写的amethod()???
System.out.println(b.i);    // 调试时b是指向子类的对象,可是i却是父类的成员变量??
b.amethod();   是父类的方法,却是子类的实现代码???
}
public void amethod(){
System.out.println(“Descend.amethod()”);
}
}
为什么运行出来的结果是
Descend.amethod()
1
Descend.amethod()
我想了解这个程序的运行机制,怎么会得到这种结果
颜色加深的地方是不理解的地方。

解决方案 »

  1.   

    这个是继承和多态的问题。
    Base b = new Descend();
    创建Descend时,看Descend类有没有默认构造函数,没有的话调用父类的默认构造函数。
    父类Base类中有amethod方法,这时,还是先查找子类复写父类的amethod方法没有。子类有amethod方法,就执行指令的amethodb.i子类的i=-1b.amethod()一样执行子类自身的方法。
      

  2.   

    Base b=new Descend();
    如果子类重写了父类的amethod()方法,那么b.amethod()就会调用子类的amethod()方法,没有重写才会调用父类的amethod()方法
      

  3.   


    那么System.out.println(b.i); 怎么打印的是1,而不是-1呢?
      

  4.   

    LZ的几个问题,其实主要是说明了java的多态机制。
    Base b=new Descend();构造一个子类实例给父类。当运行时,java会检查到底是该实例子类还是父类。
    如果是子类,会自动调用子类的方法。这就是运行时多态的体现。
    至于b.i的问题。因为多态是针对方法级别的,而成员变量没有多态。
      

  5.   

    我刚去测试了,C++的确跟java不同,但是多态机制应该不分语言吧????
      

  6.   

    Base b=new Descend();构造一个子类实例化一个父类引用。因为Java没有C++的virtual keyword.凡是子类重写父类的方法就会形成多态机制。多态机制是针对方法而言,而数据成员没有多态性。
    当运行时,如果父类引用是子类对象,就会调用子类的方法。这就是运行时多态的体现。
    而数据成员b.i没有多态性,只能引用父类的成员
      

  7.   

    http://blog.csdn.net/lovekatherine/archive/2007/07/26/1708541.aspx各位可以看看,前辈们搞不明白。
      

  8.   

    Java 中的继承:一个子类继承了某个父类,那么这个子类继承了该父类的非私有变量和方法。
    在你这段程序中Descend extends Base同时重写了amethod()方法;
    所以当你Base b=new Descend();虽然父类指向子类,但在实例化时,程序运行的还是子类重写的amethod()方法;b.i的问题。因为多态是针对方法级别的,而成员变量没有多态。
      

  9.   

    其实很简单,就像楼上说得,成员变量没有多态,多态仅针对方法级的。然后,当你创建一个子类时,系统会自动先创建其父类,直至Object类,这点你可以通过构造块进行测试。此外,JAVA源程序都首先经过编译成成为与具体平台无关的.class文件,然后程序运行时JVM加载字节码到内存,按照解释方式逐条执行。
      

  10.   

    我也学习了。
    Base b=new Descend(); 这句话叫做父类的引用指向子类的对象这是一个多态。
    当你在main中写上
    Base b=new CsdnDescend(); 
    //System.out.println(b.i); 
    //b.amethod(); 1。把后面两句注释掉 同样会打印出:Descend.amethod();
    这是因为你new的时候调用了父类的构造方法:Base();{amethod();}
    而子类重写了amethod()这个方法所以会打印出:Descend.amethod();
    2。b.i我认为b是父类的 引用 所以是调用父类声明的变量。只有方法可以重写
    3。b.amethod() 同样的这里是调用父类的amtheod方法 但因为被子类重写了,所以调用子类的amethod方法。
      

  11.   

    关于b.i为什么得到的是1,而不是-1,因为引用b其实包含了1和-1两个域,你可以去看下多台的缺点,在引用b中的i时所产生的默认域并非Descend 的i域。如果你要得到-1,必须用Descend.i显示的指明得到。