package com.bag;class Super
{
int i = 10; Super()
{
print();
i = 20;
} void print()
{
System.out.println(i);
}
}public class Sub extends Super

int j=30; 
Sub()
{
print();
j=40; 


void print()

System.out.println( j); 



public static void main(String[] args)

System.out.println(new Sub().j); 



}结果是 0
       30
       40为什么不是  10 
            30
            40

解决方案 »

  1.   

    因为子类的print()方法,覆盖了父类额print()方法.运行时候 new Sub.j(),首先去Sub类了找j的属性,Sub是继承的Super类,直接调用Super无参构造器,Super无参构造器了,调用了print()方法,执行print()方法,这个方法是被子类覆盖的,所以是调用的子类方法,输出j,j并没有赋值,int类型成员变量初始值为0所以输出0,之后执行子类Sub方法,Sub调用print(),输出j,子类里全局变量j值是30,所以输出30,之后继续执行j=40,找到Sub.j的值,输出40。总结就是子类方法覆盖了父类方法,所以父类print()调用的是子类方法。int成员变量初始值为0,所以输出0。其他成员变量初始值是什么可以自己测试看看。
      

  2.   

    print()方法覆盖是没错。
    也要了解到一个对象实例化的步骤,基本可以分为五个步骤。
    在执行new Sub();这句话的时候,先调用父类的构造方法Super();父类构造方法中调用的print()方法是子类Sub中的方法,此时还没有调用子类中的构造方法给j显性初始化赋值,所以j在栈内存中存放的还是int型的默认值0,所以此时输出0;
    接着调用子类Sub中的构造方法Sub();调用的同时为j显性初始化赋过值了,所以print();方法中j=30;
    最后,在Sub的构造方法中为j改变赋值,所以此时new Sub().j=40.
      

  3.   

    过程如下:
    1. 虚拟机试图访问Sub.main这个静态方法
    2. 当一个类第一次被访问的时候,才会被加载,如果有静态变量或称为类变量,那么在此
        加载时会被初始化
    3. 加载Sub类的时候,虚拟机注意到它有一个基类Super,那么Super类也会被加载
    4. 当new Sub()的时候,第一件事儿就是在内存中划出一块足够存储Sub对象的空间,
        这块空间会被清零,也就是说Sub对象的所有实例变量都会得到一个默认值,对于
        这里的i,j就是0,如果是引用类型就是null
    5. 执行Sub构造器,Sub有父类,所以执行Sub构造器的第一步就是执行父类的构造器, 
        构造器的执行过程是最让人迷惑的地方,下面试着做一下解释:    首先要明确构造器的作用,构造器的作用就是初始化对象,而不是创建对象。
        其次要明确,执行构造器时第一要做的就是初始化对象,然后才是运行构造器中的语句。
        什么叫初始化对象呢?就是按照语义从上到下依次执行一下你声明的字段。哥们就说这么多,你要再不明白,没招儿啦!
      

  4.   

    因为  你那个println(i);里的i  是类属性的  属于 全局变量
      而  方法 super里的i 却是局部变量
    所以~~~~~
     楼主明白了么???
      

  5.   

    你要想打10.30.40非常简单把int i=10 放到super的构造方法里面:class Super
    {
    Super()
    {
    int i = 10;
    print();
    i = 20;
    }void print()
    {
    System.out.println(i);
    }
    }