黑马程序员技术交流社区

标题: 静态的问题 [打印本页]

作者: 李敬    时间: 2012-8-11 20:10
标题: 静态的问题
class Insect {
        int i = 9;
        int j;
        Insect(){
                prt("i = "+i+",j = "+j);
                j =39;
        }
        static int x1 = prt("static Insect.x1 initialized");
        static int prt(String s){
                System.out.println(s);
                return 47;
        }
}
class Beetle extends Insect{
        int k = prt("beetle.k initialized");
        Beetle(){
                prt("k = "+k);
                prt("j = "+j);
        }
        static int x2 = prt("static Beetle.x2 initialized");
        static int prt(String s){
                System.out.println(s);
                return 63;
        }
        public static void main(String[] args) {
               
                prt("Beetle constructor");
                Beetle b = new Beetle();
        }       
}
打印结果:
static Insect.x1 initialized
static Beetle.x2 initialized
Beetle constructor
i = 9,j = 0
beetle.k initialized
k = 63
j = 39

对于运行结果很是迷茫
帮忙分析下程序运行的过程.
作者: 王程    时间: 2012-8-11 21:01
  1. class Insect {
  2. int i = 9;
  3. int j;
  4. Insect(){
  5. prt("i = "+i+",j = "+j);
  6. j =39;
  7. }
  8. static int x1 = prt("static Insect.x1 initialized");
  9. static int prt(String s){
  10. System.out.println(s);
  11. return 47;
  12. }
  13. }
  14. class Beetle extends Insect{
  15. int k = prt("beetle.k initialized");
  16. Beetle(){
  17. prt("k = "+k);
  18. prt("j = "+j);
  19. }
  20. static int x2 = prt("static Beetle.x2 initialized");
  21. static int prt(String s){
  22. System.out.println(s);
  23. return 63;
  24. }
  25. public static void main(String[] args) {

  26. prt("Beetle constructor");
  27. Beetle b = new Beetle();
  28. }
  29. }
  30. 打印结果:
  31. static Insect.x1 initialized
  32. static Beetle.x2 initialized
  33. Beetle constructor
  34. i = 9,j = 0
  35. beetle.k initialized
  36. k = 63
  37. j = 39

复制代码
程序从入口开始执行,所以从main开始执行,prt("Beetle constructor");这句话用到了prt这个方法,因为Beetle类中有这个方法,所以需要加载Beetle这个类,又因为Beetle类继承了Insect这个类,Java虚拟机在加载子类时会先加载父类,所以先加载了Insect这个类。
因为父类中有static int x1 = prt("static Insect.x1 initialized")以及static int prt(String s),都是静态的,所以在父类被加载时,静态成员和静态方法也一起被JVM加载了,所以就输出了第一句话static Insect.x1 initialized。
父类加载完成后,加载子类,子类中也有静态成员与静态方法,所以第二句也就出来了。static Beetle.x2 initialized
当所需要的类都被加载完成后,接下来就执行了prt("Beetle constructor");语句,所以第三句话就这么来的Beetle constructor。
接下来执行Beetle b = new Beetle();
因为要new一个对象,所以用到了Beetle的构造函数,子类的构造函数默认的第一句是一句隐式super();调用的父类无参的构造函数,所以prt("i = "+i+",j = "+j);这句话就被执行了,所以第四句语句就这么来的i = 9,j = 0。调用完父类的无参构造函数后,调用了子类无参的构造函数,Beetle(){prt("k = "+k);prt("j = "+j);}因为用到了K这个值,所以int k = prt("beetle.k initialized");这句话就被执行了,beetle.k initialized这句就被打印出来了,接下来最后两句楼主应该能看懂的,就是两句输出语句。






作者: 张雪磊    时间: 2012-8-11 21:02
本帖最后由 张雪磊 于 2012-8-11 21:07 编辑

java在加载类,当读到下面主函数中蓝色的那句代码后就对类进行初始化,首先是初始化父类的静态定义(如果有父类的话),然后是子类的静态定义;再接着就是父类的定义初始化、父类的构造函数初始化;最后才是子类定义初始化、子类构造函数。

下面我用数字表示执行步骤
class Insect {
        int i = 9;
        int j;
        Insect(){
                prt("i = "+i+",j = "+j);// 7,这句代码又调用了prt 函数,这时候 j 还没有赋值,等于0。所以又打印了一句“i = 9,j = 0 ”。
                j =39;
        }
        static int x1 = prt("static Insect.x1 initialized");// 1,主函数蓝色那句代码执行,类加载进内存后会先初始化父类的静态定义,由于这句话调用了prt 方法,所以执行下面那个
                                                                              //         函数了

        static int prt(String s){
                System.out.println(s);//2, 上面那句代码1调用了这个函数,这个函数就执行了,打印了传入的参数  "static Insect.x1 initialized" ,然后返回了47,上面的x1就等于47了
                return 47;
        }
}
class Beetle extends Insect{
        int k = prt("beetle.k initialized");//9,这句再次调用了prt函数,打印了参数 "beetle.k initialized" ,返回63,k就等于63
        Beetle(){
                prt("k = "+k);//8,最后是初始化子类构造函数,这里用到 k 的值,所以转而执行上面那句,执行完上面那句后,k的值等于63,调用prt函数打印的就是k = 63 。
                prt("j = "+j);//10,这句用到父类的静态变量,通过父类构造函数的初始化,j的值已经变成39,这样调用prt函数打印的就是 j = 39 。至此结束
        }
        static int x2 = prt("static Beetle.x2 initialized");// 3, 然后是初始化子类的静态定义,这句话调用了子类的 prt 方法,所以又去执行了下面子类的prt方法
        static int prt(String s){
                System.out.println(s);//4,同样,上面的代码3调用了这个方法,方法执行,打印传入的参数 "static Beetle.x2 initialized "  ,返回63,x2就等于63了
                return 63;
        }
        public static void main(String[] args) {
               
                prt("Beetle constructor");//5,初始化动作做完后,就开始真正执行这句代码了,这句代码是调用了上面 4 那个方法,就打印了传入的参数"Beetle constructor"
                Beetle b = new Beetle();//6,然后开始执行这句话,这个就相对简单了,创建子类对象,由于子类构造函数第一句默认是super(),所以先初始化父类构造函数
                                                     //转入执行上面的 7

        }        
}


作者: 郑正华    时间: 2012-8-11 21:08
本帖最后由 郑正华 于 2012-8-11 21:12 编辑

首先跟你说下,当代码中有继承关系,而且有静态成员时,加载的顺序是这样的(从上往下的顺序):
父类:静态变量或静态初始化块
子类:静态变量或静态初始化块
父类:变量
父类:初始化块
父类:构造器
子类:变量
子类:初始化块
子类:构造器
---------------------------------------------------
接下来我们看下代码的执行流程:
class Insect {
         int i = 9;
          int j;
         Insect() {
               prt("i = " + i + ",j = " + j);←5.执行父类的构造方法,打印 出 “i = 9,j = 0”;返回39给变量j;
               j = 39;
         }
         static int x1 = prt("static Insect.x1 initialized");  ←1.加载父类的静态变量,执行父类的prt()静态方法。返回47给x1;
         static int prt(String s) {
              System.out.println(s);
               return 47;
         }
}
class Beetle extends Insect {
           int k = prt("beetle.k initialized");←6.加载子类的变量,但因为变量调用了子类的prt静态方法,所以打印出"beetle.k initialized",并且返回63给变量k;
            Beetle() {              ←7.加载子类的构造器,执行构造器里的方法。
           prt("k = " + k);
           prt("j = " + j);
            }
           static int x2 = prt("static Beetle.x2 initialized");←2.加载子类的静态变量,执行子类的prt()静态方法,返回63给x2;
           static int prt(String s) {
            System.out.println(s);
           return 63;
          }
          public static void main(String[] args) {

            prt("Beetle constructor");  ←3.调用子类的prt()静态方法,打印"Beetle constructor";  
            Beetle b = new Beetle(); ←4.实例化Beetle类。调用Beetle类的构造方法,但因为子类的构造方法里有一个默认的super()语句,所以先调用父类的构造方法。
            
          }
}

楼主也可以参考一下:http://wenku.baidu.com/view/07de511c59eef8c75fbfb3bb.html

回答个问题不容易,希望楼主的问题能够解决~不再有疑惑~

作者: 张雪磊    时间: 2012-8-11 21:11
郑正华 发表于 2012-8-11 21:08
首先跟你说下,当代码中有继承关系,而且有静态成员时,加载的顺序是这样的(从上往下的顺序):
父类:静 ...

。。。。。。。。。。。。。
作者: 郑正华    时间: 2012-8-11 22:37
张雪磊 发表于 2012-8-11 21:11
。。。。。。。。。。。。。

!!!!!!!!!!!!!!!!!!!!!{:2_37:}




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2