JAVA的一道面试题

时间:2022-09-01 11:29:02

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~
正好我对这种带有自身类型的字段的情况有些迷糊,索性答曰:“有变量未初始化,编译器可能会报错”~

我想问的是,如果忽略未初始化错误的话,以上代码执行顺序到底如何?

65 个解决方案

#1


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

#2


14235

#3


好吧~  静态变量会自动初始化为0…………  这下囧了~

#4


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

#5


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

#6


根据static 对象的性质,程序的执行流程为:

Test tester = null;
int count1 = 0;
int count2 = 0;

tester = new Test();

       count1 ++;
       count2 ++;
       输出 1 1

count2 = 0;
最终结果为1 0,输出为1 1

#7


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

#8


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


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

#9


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

#10


步骤如同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.

#11


一个笔误,顺序是14235

#12


搞清顺序输出结果自然就出来了,顶6楼

#13


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.

#14


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
然后接下来就不用再说了吧。

#15


10L受教了~

#16


呵呵看清楚了

#17


该回复于2012-02-23 13:10:35被版主删除

#18


赞~!10L

#19


我感觉应该是12345,这么个执行顺序。
jvm加载class文件后,首先给静态变量 开辟空间然后初始化。所以123都符合,1我也党他是静态变量看了,这个比较迟疑。

jvm把静态变量初始化完毕后,就调用构造方法,也就是4.

最后才是调用方法。
=====================
我是这么理解的,不对的地方请直接说明。

#20


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

#21


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

#22


受教了!

#23


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

高手,学习了,明白了!

#24


OK,多谢了~ 赶紧结贴……  区区50分不够你们分的~

#25


17楼有人回复被删了~  我很好奇他说的啥呢? 版主干嘛这么凶残~

#26


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

#27


学习了 呵呵 

#28


受教了!

#29


学习了,帮助新手成长的好题目

#30


看看,顶下

#31


输出11

#32


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

#33


实践证明,答案为 11

#34


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

#35


引用 19 楼 ruiz_info 的回复:
我感觉应该是12345,这么个执行顺序。
jvm加载class文件后,首先给静态变量 开辟空间然后初始化。所以123都符合,1我也党他是静态变量看了,这个比较迟疑。

jvm把静态变量初始化完毕后,就调用构造方法,也就是4.

最后才是调用方法。
=====================
我是这么理解的,不对的地方请直接说明。

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

#36


我还的努力啊

#37


10L正解,惭愧啊~~~。

#38


10L给力啊,对于新手的我学习了,惭愧啊

#39


应该是1和0

首先...JVM会给他们一个默认值0  0

单例运行(静态的) 1  1

之后赋值..1 0(1被冲掉了)

如果你把单例的那句话放在构造方法后面,就是1 1了

这跟JVM有关系,建议楼主看深入JVM虚拟机,你就会明白了。。

#40


关键是在实例化对象和初始化变量的顺序上

#41


受教了,不错例题.

#42


有些人已经给出答案了,但是这道题如果这样出就更好了。

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

#43


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

#44


结果是11啊。。没错误啊

#45


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

#46


一女生跟男朋友分手了,旁边她同学安慰她:“那男的有什么好的,土木工程的,一听就知道又“土”又“木”的!”旁边软件工程的男同学一听,心都凉了半截。。。

#47


重点 考的是 单例模式吧

#48


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

所以考察的是类加载时静态变量的初始化过程。

#49


LZ,这题毫无难度啊

#50


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

#1


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

#2


14235

#3


好吧~  静态变量会自动初始化为0…………  这下囧了~

#4


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

#5


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

#6


根据static 对象的性质,程序的执行流程为:

Test tester = null;
int count1 = 0;
int count2 = 0;

tester = new Test();

       count1 ++;
       count2 ++;
       输出 1 1

count2 = 0;
最终结果为1 0,输出为1 1

#7


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

#8


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


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

#9


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

#10


步骤如同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.

#11


一个笔误,顺序是14235

#12


搞清顺序输出结果自然就出来了,顶6楼

#13


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.

#14


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
然后接下来就不用再说了吧。

#15


10L受教了~

#16


呵呵看清楚了

#17


该回复于2012-02-23 13:10:35被版主删除

#18


赞~!10L

#19


我感觉应该是12345,这么个执行顺序。
jvm加载class文件后,首先给静态变量 开辟空间然后初始化。所以123都符合,1我也党他是静态变量看了,这个比较迟疑。

jvm把静态变量初始化完毕后,就调用构造方法,也就是4.

最后才是调用方法。
=====================
我是这么理解的,不对的地方请直接说明。

#20


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

#21


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

#22


受教了!

#23


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

高手,学习了,明白了!

#24


OK,多谢了~ 赶紧结贴……  区区50分不够你们分的~

#25


17楼有人回复被删了~  我很好奇他说的啥呢? 版主干嘛这么凶残~

#26


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

#27


学习了 呵呵 

#28


受教了!

#29


学习了,帮助新手成长的好题目

#30


看看,顶下

#31


输出11

#32


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

#33


实践证明,答案为 11

#34


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

#35


引用 19 楼 ruiz_info 的回复:
我感觉应该是12345,这么个执行顺序。
jvm加载class文件后,首先给静态变量 开辟空间然后初始化。所以123都符合,1我也党他是静态变量看了,这个比较迟疑。

jvm把静态变量初始化完毕后,就调用构造方法,也就是4.

最后才是调用方法。
=====================
我是这么理解的,不对的地方请直接说明。

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

#36


我还的努力啊

#37


10L正解,惭愧啊~~~。

#38


10L给力啊,对于新手的我学习了,惭愧啊

#39


应该是1和0

首先...JVM会给他们一个默认值0  0

单例运行(静态的) 1  1

之后赋值..1 0(1被冲掉了)

如果你把单例的那句话放在构造方法后面,就是1 1了

这跟JVM有关系,建议楼主看深入JVM虚拟机,你就会明白了。。

#40


关键是在实例化对象和初始化变量的顺序上

#41


受教了,不错例题.

#42


有些人已经给出答案了,但是这道题如果这样出就更好了。

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

#43


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

#44


结果是11啊。。没错误啊

#45


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

#46


一女生跟男朋友分手了,旁边她同学安慰她:“那男的有什么好的,土木工程的,一听就知道又“土”又“木”的!”旁边软件工程的男同学一听,心都凉了半截。。。

#47


重点 考的是 单例模式吧

#48


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

所以考察的是类加载时静态变量的初始化过程。

#49


LZ,这题毫无难度啊

#50


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