public class Sub extends Super {
    int argA;
    static int argB;
    int argC = 13;
    {
     System.out.println("动态语句块:Sub.argA = " + (argA = 11));
    }
    static{
     System.out.println("静态语句块:Sub.argB = " + (argB = 12));
    }
    Sub(){
     //super();
     System.out.println("构造方法块:Sub.argC = " + argC);
     print();
        print(argB);
        argA = 30;
    }    void print(int argA) {
     System.out.println("sub.print(args)");
        System.out.println(argA);
    }
    
    void print(){
     System.out.println("sub.print()");
     System.out.println(argA);
        System.out.println(argB);
    }    public static void main(String[] args) {
        System.out.print(new Sub().argA);
    }
}class Super {
    protected int argA = 21;
    protected static int argB;
    static{
     argB = 22;
    }
    Super() {
        print();
        print(argA);
        argA = 23;
    }    void print(int argA) {
     System.out.println("super.print(args)");
        System.out.println(argA);
    }
    
    void print() {
     System.out.println("super.print()");
     System.out.println(argA);
        System.out.println(argB);
    }
}
执行过程是这样的吗?
static int argB;
int argA;
int argC;
static{
System.out.println("静态语句块:Sub.argB = " + (argB = 12));
}
Sub(){
super();
argC = 13;
        System.out.println("动态语句块:Sub.argA = " + (argA = 11));
System.out.println("构造方法块:Sub.argC = " + argC);
print();
    print(argB);
    argA = 30;
}
求解释。

解决方案 »

  1.   

    真实的输出为:
    ******************************************************
    静态语句块:Sub.argB = 12
    sub.print()
    0
    12
    sub.print(args)
    21
    动态语句块:Sub.argA = 11
    构造方法块:Sub.argC = 13
    sub.print()
    11
    12
    sub.print(args)
    12
    30
    **************************************************
    分析:
    main方法:new Sub().argA  首先,new 一个Sub对象,在new Sub对象时先new 其父类,所以先调用父类的静态块:argB = 22
    此时,Super.argB = 22。再调用子类的静态块:argB = 12,此时,Sub.argB = 12。
    输出1:
    静态语句块:Sub.argB = 12
      继续,创建对象,父类开始,变量初始化,Super.argA = 21,调用父类构造方法print();print(argA);argA = 23;
      由于print()方法被子类重写,所以实际调用的是子类的print()方法
    输出2:
    sub.print()
    0 //Subr.argA = 0;
    12 //Sub.argB = 12
      由于print(argA)方法被子类重写,所以实际调用的是子类的print(argA)方法,调用者是父类,传进去的是Super.argA = 21
    输出3:
    sub.print(args)
    21 //父类传进去的21
      之后,argA = 23,此时Super.argA = 23,Super.argB = 22。
      父类创建好了之后,创建子类,变量初始化,argC = 13 后执行动态块
    输出4:
    动态语句块:Sub.argA = 11  //此时Sub.argA = 11,动态块中赋的值。
      调用子类的构造方法:System.out.println("构造方法块:Sub.argC = " + argC);print();print(argB);argA = 30;
    输出5:
    构造方法块:Sub.argC = 13 
      调用子类print();print(argB);
    输出6:
    11 //Sub.argA
    12 //Sub.argB
    sub.print(args)
    12 // 调用时传入的是Sub.argB
      构造方法最后一句:argA = 30;此时Sub.argA = 30,Sub.argB = 12,Sub.argC = 13。
      main方法中print了new Sub().argA
    最后输出:
    30 //Sub.argA = 30
      

  2.   

    mian方法做点修改,你运行之后就能理解了,看看*线后面的结果    public static void main(String[] args) {
            Sub s = new Sub();
            Super f = (Super) s;
            System.out.println("**********************************");
            System.out.println("Sub.argA : "+s.argA);
            System.out.println("Sub.argB : "+s.argB);
            System.out.println("Sub.argC : "+s.argC);
            System.out.println("Super.argA : "+f.argA);
            System.out.println("Super.argB : "+f.argB);
            //System.out.print(f.argC);
        }
      

  3.   

    Sub的主动使用 ,先加载父类 Supper,执行以下
    protected static int argB;  //设置为默认值 0 ;
        static{
            argB = 22; //初始化为 22
        }接着加载子类Sub
    static int argB;
        int argC = 13;
        {
            System.out.println("动态语句块:Sub.argA = " + (argA = 11));
        }
    执行父类构造方法
    Super() {
            print();
            print(argA);
            argA = 23;
        }子类构造方法
    Sub(){
            //super();
            System.out.println("构造方法块:Sub.argC = " + argC);
            print();
            print(argB);
            argA = 30;
        }
      

  4.   

    你在每一步中加入调试信息 System.out.println() 就知道是怎么运行法了
      

  5.   

    public class Sub extends Super {
        int argA;
        static int argB;
        int argC = 13;
        { //这里应该是在new 一个Sub实例的时候才打印
            System.out.println("动态语句块:Sub.argA = " + (argA = 11));
        }
        static{
         System.out.println("------------Sub()静态数据模块.-----------") ;
            System.out.println("静态语句块:Sub.argB = " + (argB = 12));
        }
        Sub(){
            //super();
            System.out.println("构造方法块:Sub.argC = " + argC);
            print();
            print(argB);
            argA = 30;
        }    void print(int argA) {
            System.out.println("sub.print(args)");
            System.out.println(argA);
        }
        
        void print(){
            System.out.println("sub.print()");
            System.out.println(argA);
            System.out.println(argB);
        }    public static void main(String[] args) {
            System.out.print(new Sub().argA);
        }
    }class Super {
        protected int argA = 21;
        protected static int argB;
        static{
         System.out.println("------------Supper()静态数据模块.-----------") ;
            argB = 22;
        }
        Super() {
         System.out.println("------------Supper()构造函数 begin.-----------") ;
            print();
            print(argA);
            argA = 23;
            System.out.println("------------Supper()构造函数 end.-----------") ;
        }    void print(int argA) {
            System.out.println("super.print(args)");
            System.out.println(argA);
        }
        
        void print() {
         System.out.println("------------Supper().print() begin .-----------") ;
            System.out.println("Supper().argA = " + argA);
            System.out.println("Supper().argA = " + argB);
            System.out.println("------------Supper().print() end .-----------") ;
            
        }
    }结果:
    ------------Supper()静态数据模块.-----------
    ------------Sub()静态数据模块.-----------
    静态语句块:Sub.argB = 12
    ------------Supper()构造函数 begin.-----------
    sub.print()
    0
    12
    sub.print(args)
    21
    ------------Supper()构造函数 end.-----------
    动态语句块:Sub.argA = 11
    构造方法块:Sub.argC = 13
    sub.print()
    11
    12
    sub.print(args)
    12
    30
      

  6.   


    public class Sub extends Super {
        int argA;//(12)
        static int argB;//(4)
        int argC = 13;//(13)
        {
            System.out.println("动态语句块:Sub.argA = " + (argA = 11));//(14)
        }
        static{
            System.out.println("静态语句块:Sub.argB = " + (argB = 12));//(5)
        }
        Sub(){
            //super();
            System.out.println("构造方法块:Sub.argC = " + argC);//(15)
            print();//(16)
            print(argB);//(18)
            argA = 30;//(20)
        }    void print(int argA) {
            System.out.println("sub.print(args)");//(10),(19)
            System.out.println(argA);//(10)Super.argA = 21,(19)Sub.argB=12
        }
        
        void print(){
            System.out.println("sub.print()");//(8),(17)
            System.out.println(argA);//(8),Sub.argA = 0,(17)Sub.argA=11
            System.out.println(argB);//(8),Sub.argB = 12,(17)Sub.argB=12
        }    public static void main(String[] args) {
            System.out.print(new Sub().argA);//(1),(21)Sub.argA=30
        }
    }class Super {
        protected int argA = 21;//(6)
        protected static int argB;//(2)
        static{
            argB = 22;//(3)
        }
        Super() {
            print();//(7)
            print(argA);//(9)
            argA = 23;//(11)
        }    void print(int argA) {
            System.out.println("super.print(args)");
            System.out.println(argA);
        }
        
        void print() {
            System.out.println("super.print()");
            System.out.println(argA);
            System.out.println(argB);
        }
    }
      

  7.   

    没看到main函数在Sub类里,应该先初始化static类型和静态块,然后再执行main函数.
    应该是2-5,1,然后6-21如果main函数在其他类(如Test类),执行顺序就是1-21
      

  8.   

    我认为是这样的:
    System.out.print(new Sub().argA);
    当前对象的类型是Sub,传入父类构造函数的对象类型就是Sub
    父类中print()等价于this.print(),此时this类型是刚才传入的对象类型Sub
    这一点可以通过代码验证    Super() {
         System.out.println(this.getClass());
            print();
            print(argA);
            argA = 23;
        }输出是class Sub
    由于Sub覆盖了父类的方法,所以就会去执行父类的方法。如果换成System.out.print(new Super().argA);
    那么this的类型就是Super,就会执行父类的方法
      

  9.   


    纠正下,笔误。
    输出是class Sub
    由于Sub覆盖了父类的方法,所以就会去执行Sub类的方法。
      

  10.   

    To Mourinho
    用this来描述,确实让我又更正些理解。因为我喜欢加this,理清了覆盖的问题。To 五哥
    谢谢,描述的很清晰。To #1楼
    感觉说法有点点问题。最后那些args打印出什么,我不关心。
    主要关心的问题是,
    问题一:为什么要覆盖,或者说会覆盖?
    问题二:变量的声明和初始化跟构造方法之间顺序问题。顺便说下:本看到一大堆解释可能会扫的很快所以如有误解,很抱歉。
      

  11.   

    这个解释容易接受.
    另外为了把静态的部分和产生对象分开,测试时可以用Class.forName()加载类,那些静态的部分只执行一次。
    对于理解初始化过程会减低难度。