public class Test{
    private static Test tester = new Test(); //step 1
    private static int count1;               //step 2
    private static int count2 = 0;           //step 3
    public Test(){                           //step 4
        count1++;
        count2++;
        System.out.println("" + count1 + count2);
    }
    public static Test getTester(){          //step 5
        return tester;
    }
    
    public static void main(String[] args){
       Test.getTester();
    }
}问:以上代码执行的顺序~,输出的结果~这是我昨天面试时碰到的一题,我尽量还原了原题。先说一下,这里count1未初始化可不是我忘了,原题就是这么搞D~
正好我对这种带有自身类型的字段的情况有些迷糊,索性答曰:“有变量未初始化,编译器可能会报错”~我想问的是,如果忽略未初始化错误的话,以上代码执行顺序到底如何?

解决方案 »

  1.   

    应该只会执行
    Test tester = new Test(); 吧。
      

  2.   

    更正一下,原题是 count2 = 2;
      

  3.   

    这道题的考点在 运算符从左到右的结合原则,即:
     System.out.println("" + count1 + count2); \\首先空字符串和count1进行运算,得到1,然后这个字符再和数字count2进行运算,此时得到一个新字符串,也就是本题结果:11
      

  4.   

    根据static 对象的性质,程序的执行流程为:Test tester = null;
    int count1 = 0;
    int count2 = 0;tester = new Test();       count1 ++;
           count2 ++;
           输出 1 1count2 = 0;
    最终结果为1 0,输出为1 1
      

  5.   

    debug晕了…… 先不结贴,坐等又帅又厉害的好人~
      

  6.   


    再根据楼主问题补充两点:
    1.本题的成员变量count1,不是final类型的,所以不是必须初始化,更不会编译错误
    2.本题的执行顺序,就是创建对象(new)的基本顺序,先初始化static,然后构造方法.....
      

  7.   

    我把LZ的代码考下来运行了一下,结果是:11  
    但是,我把count2的值改一下(不管改成什么),其结果总是:11
    还有不管怎么改count1的值也是同样的情况,这是为什么啊?
    我初学java,基础不够,望多多指教啊!!!
      

  8.   

    步骤如同6L所说:1,JVM虚拟机启动是通过引导类加载器(Bootstrap Class Loader)加载一个初始化类来完成,这个类由虚拟机的具体实现指定,也就是一般意义上的启动类(主类);然后虚拟机链接这个类,初始化并调用它的public void main(String[])方法。2,面试题中根据上下文可认为初始化类就是Test类,所以:
      a, 首先装载这个类,然后在链接的准备阶段(链接包括验证、准备、引用三个阶段),为所有类(静态)变量分配内存,设为为默认值(Test tester = null; int count1 = 0; int count2 = 0;)  b, 链接完成后,进行(类)初始化,按代码中声明顺序进行类(静态)变量的初始化,也就是先调用
            private static Test tester = new Test(); //step 1
         注:这里省略了基类初始化和<clinit>的相关细节。  c, 上述步骤中的new 触发Test类的实例化(对象创建),先在堆上分配内存,然后设置对象变量(本例中没有)为初始值,然后调用<init>,细节略过,简单来讲这里会导致构造方法的调用,也就是:
          public Test(){                           //step 4
            count1++;
            count2++;
            System.out.println("" + count1 + count2);
        }
        很显然,这时候的count1和count2并没有被初始化,只是简单的被设置为默认值0(在链接的准备阶段)。所以打印出来的值总是11。  d, 接下来继续按声明顺序执行初始化,也就是:
        private static int count1;               //step 2
        private static int count2 = 2;           //step 3  e, 初始化完成之后,完成了初始类的加载,跳转到main方法开始执行。所以顺序为14253,并且无论count2 和 count1为多少,打印出来的总是11.;如果交换一下顺序,比如
      count 2 = 2;
      new test();  那么打印的结果将是13.
      

  9.   

    6L 10L正解
    的确是14235
    只要注意在4的时候    private static int count1;               //step 2
        private static int count2 = 0;           //step 3这2句话并没有被执行,所以count1 = count2 = 0;
    完成++操作后,值都变为1.
    所以不管怎样改变2,3中count1,count2的值,打印出来的总是1.
      

  10.   

    Test.getTester();
    JVM规定当4中情况下会出事类,其中一种酒是调用类的静态方法的时候。所以很明显这里调用Test的静态方法getTester所以Test会进行初始化。那么static的部分会被触发。根据初始化的顺序,那么很明显应该执行:
    private static Test tester = new Test();
    然后
    private static int count1
    private static int count2
    也会被初始化,但是由于他们是int型的,所以初始化为0
    这里就是创建Test对象咯,接下来就是进入Test的构造方法,
    count1++;
    count2++;
    System.out.println("" + count1 + count2);
    由于count2还没有进行赋值,所以它目前为0;所以 ++后count1和count2都是1
    然后接下来就不用再说了吧。
      

  11.   

    我感觉应该是12345,这么个执行顺序。
    jvm加载class文件后,首先给静态变量 开辟空间然后初始化。所以123都符合,1我也党他是静态变量看了,这个比较迟疑。jvm把静态变量初始化完毕后,就调用构造方法,也就是4.最后才是调用方法。
    =====================
    我是这么理解的,不对的地方请直接说明。
      

  12.   

    其实main函数中掉不调用函数输出结果是一样的,楼主要记住,java中整型的可以不设置初始化值,默认为0,所以该类没有错误。
    你如果能理解类的加载顺序就清除了,就简单说你写的这个类,先加载静态变量,所以第一个是private static Test tester = new Test(); 但是你调用了构造方法,所以会去加载够着方法,这个时候另外两个静态变量并没有赋值。默认值为0,++操作后就是1了,输出结构是11;
    楼主可以把main中的方法调用和getTester()方法去掉,运行空的main方法,结果应该一样。
    仅仅个人理解
      

  13.   

    执行顺序2314
    count1因为是字段,所以它会被分配默认值0
    输出11
      

  14.   

    运行顺序应该是14235,吧,全局变量不初始化,他就自动赋默认值,int类型0,要count是2的话,结果就是1 3喽
      

  15.   

    这题最有意思的是,main 方法中的 语句有与没有输出都是 1 1
      

  16.   

    debug 一下,step by step ,能明白类运行的具体过程
      

  17.   

    我也觉得是12345,如果count2=0最后输出结果为11,如果为2最后结果为13
      

  18.   

    应该是1和0首先...JVM会给他们一个默认值0  0单例运行(静态的) 1  1之后赋值..1 0(1被冲掉了)如果你把单例的那句话放在构造方法后面,就是1 1了这跟JVM有关系,建议楼主看深入JVM虚拟机,你就会明白了。。
      

  19.   

    有些人已经给出答案了,但是这道题如果这样出就更好了。public class Test{
        private static Test tester = new Test(); //step 1
        private static int count1;               //step 2
        private static int count2 = 0;           //step 3
        public Test(){                           //step 4
            count1++;
            count2++;
            System.out.println("count1=" + Test.count1);
            System.out.println("count2=" + Test.count2);
        }
        public static Test getTester(){          //step 5
            return tester;
        }
        
        public static void main(String[] args){
           System.out.println("count1=" + Test.count1);
           System.out.println("count2=" + Test.count2);
        }
    }这里我给大家总结一个结论啊:永远不要给一个静态变量赋值默认的初始值,例如step3
      

  20.   

    也就是你不要如下这样:
    private static int count2 = 0;           //step 3
    你这样倒是可以的
    private static int count2 = 3;           //step 3
    0是默认的初始值,没有必要再 = 0 这样写,这样写有可能覆盖了初始化时赋的值,如例题那样,如果你赋值
     = 3 ,你可能是有意要赋值为3,这是你有意覆盖的,这样还有些可接受。
    我是这样得出的结论,而且我记得:在eclipse中如果例题这样写程序,在step3 处会用黄色标注警告信息,我感觉就是我分析的这个原因,大家认为呢?
      

  21.   

    大家不给力呀,开动开动脑筋啊!
    我目测,这道题绝对不是招聘码奴级别程序员的,应该是一个大公司招聘高级java程序员的题目,如果这道题出的如我修改的那样,这道题才是考到点子上了。
    这就是那类让码奴咒骂出题者的题,他们会非常气愤:“我不思考这些程序细节,我就是能写好程序不行啊!”
    楼主可不可以爆一下,这套题的面试目标应聘者的薪金范围是不是在8k~15k之间?你研究的越深入,你的身价也越高,这是码奴们及其反感的事。
    码奴时我们每个程序员都要经过的一段道路,但是有些人(大部分)就停止了码奴的级别不肯进取了。这样不好,为了摆脱码奴的身份,尽量把所有能考虑的细节都去思考一番,绝不整天在论坛抱怨公司,设想如何在30岁前转行。
    说的有点离题了啊,就是最近面试应聘者的那些问题太简单了,还有些人大大抱怨太难,我的那些都根本没有这个1%难。
      

  22.   

    这确实有个单例,但是不是单例模式,请看:
    public Test(){ ...
    构造器是公有的。
    这道题考察的是:是否知道一个类加载时静态变量的初始化过程,其中还加入了一个对象实例化的影响,因为一个类加载时先把静态变量赋值为默认值,然后再初始化赋值,在赋值时又有一个对象被实例化了,构造器有影响了初始化值,最后 count2 = 0;又把构造器对count2的影响给抹掉了。所以考察的是类加载时静态变量的初始化过程。
      

  23.   

    弄懂了;""这个玩意让count1、count2转成字符串连接了。
    count1++;
    count2++;
    System.out.println("" + count1 + count2);
      

  24.   

    已经有很多人都分析的比较透彻了,其实最简单的方法就是用eclipse的Debug功能运行一下,观察执行过程
      

  25.   

    题目可以改一下:
    public static void main(String[] args){
           new Test().getTester();
    }
      

  26.   

    public class Test{
        private static Test tester = new Test(); //step 1
        private static int count1;               //step 2
        private static int count2 = 0;           //step 3
        public Test(){                           //step 4
            count1++;
            count2++;
            System.out.println("" + count1 + count2);
        }小弟还有一点不是很懂,执行count1++,这时候如果step2没有声明的话那就应该没有count1这个变量,所以就应该先执行了step2,所以我认为是不是这样的顺序--1234,然后count2的赋值是没有执行的,只有声明,执行构造方法后然后才赋值的呢???请有空的高手指点下。。
      

  27.   

    唉,来晚了,围观一下吧!这个是考类的加载及初始化及实例化顺序的题,推荐一个视频吧,我下载过圣思园的一个java视频,讲的很到位,看完大家都会明白的!我不是做广告,请大家不要拍我!
      

  28.   

       回答一下54#的问题吧,java在初始化时,会由上向下进行static变量的初始化,即为static变量赋于java规定的初始值,因此初始化时:tester变量的值为null,count1因为是int类型java规定的初始值为0;count2的初始值因为也是int因此初始值也是0;
       这时初始化完毕,开始由上向下进行赋值操作,一楼问的问题也由这个时间点开始,因此为tester赋值了new  Test(); 因此触发了test()构造函数的执行,这时执行了count1++,count2++,根据初始化的结果,执行完后,count1 = 1,count2=1,因此打印出来的结果就是11;
       然后继续向下赋值,因为count1没有赋值操作,因此结果还是1,而count2有赋值操作,因此java使用了1这个赋值操作为count2赋值;然后就是main中写的Test.getTester()方法的执行了.
        因此最后执行顺序为:14235!
      

  29.   

    这个问题可以参考一下类的加载顺序,然后这个问题就一目了然了。
    JVM 加载步骤,1、装载 2、连接 3、初始化
    那么类成员默认值是什么时候设置的呢? 在连接阶段(这个阶段是不执行任何java代码的)。
    各类型的成员的初始值大家都知道的。
    然后就是初始化,顺序执行!
    所以14235的执行顺序是正解。补充,执行 4 时, 2,3还未执行,但已经有初始值(连接操作时)。
    所以输出一直是 1 1