黑马程序员技术交流社区

标题: 分享别处看到的一个笔试题,据说考倒90%以上人。 [打印本页]

作者: 黑马伍哲沂    时间: 2013-4-11 19:52
标题: 分享别处看到的一个笔试题,据说考倒90%以上人。
本帖最后由 黑马伍哲沂 于 2013-4-11 20:11 编辑
  1. class CodeTest
  2. {
  3.         static
  4.         {
  5.                 System.out.println("1");
  6.         }
  7.         {
  8.                 System.out.println("2");
  9.         }
  10.         public CodeTest ()
  11.         {
  12.                 System.err.println("3");
  13.         }
  14.         public static void main(String[] args)
  15.         {
  16.                 new CodeTest();
  17.         }
  18. }
复制代码
请写出运行结果。
提示:可能大家会觉得静态代码块,构造代码块还有构造函数,毕老师都讲的很清楚了。
也很自信这个程序的答案。但请更细心点。

作者: 秦久启    时间: 2013-4-11 20:06
程序有明显的错误啊,public TestErr()    System.err.println("3");这两个写的应该是这样吧,public CodeTest()     System.out.println("3");如果是这样的话答案应该是
1
2
3
作者: 黑马伍哲沂    时间: 2013-4-11 20:09
秦久启 发表于 2013-4-11 20:06
程序有明显的错误啊,public TestErr()    System.err.println("3");这两个写的应该是这样吧,public CodeT ...

改过来了,构造函数写错了,输出语句没错。就是那样的。
作者: 谭威    时间: 2013-4-11 20:26
程序首先在main方法中执行new CodeTest();会先去加载这个类父类中的静态代码块,如果有的话,你这个类没继承任何类,那么它只会执行自己类中的静态代码块,所以先打印出System.out.println("1");,然后去执行父类中的非静态代码块,也就是构造代码块。父类中没有,接着执行父类的构造方法;父类的构造方法执行完毕之后,它接着去看子类有没有构造代码块,如果有就执行子类的构造代码块。子类的构造代码块执行完毕再去执行子类的构造方法 System.err.println("3");
作者: 丘凤光    时间: 2013-4-11 20:57
JVM虚拟机应该是找main函数作为程序的入口,所以会先执行new CodeTest();
按优先级:静态代码块——>非代码块——>构造函数。随后输出的结果应该是
1
2
3
作者: 蓝色骨头    时间: 2013-4-11 21:16
1
2
3

初始化顺序是

父类静态成员变量和静态初始化块,按在代码中出现的先后顺序,静态代码块和静态变量参与共同的排序
子类静态成员变量和静态初始化块,按在代码中出现的先后顺序,静态代码块和静态变量参与共同的排序
父类非静态成员变量和代码块,按在代码中出现的先后顺序,非静态代码块和非静态变量参与共同的排序
父类构造器
子类非静态成员变量和代码块,按在代码中出现的先后顺序,非静态代码块和非静态变量参与共同的排序
子类构造器
作者: HM朱蛟    时间: 2013-4-11 23:39
我觉得只要你看了毕老师的视频这题没理由出错哦
作者: 李尧    时间: 2013-4-11 23:44
我发现我不会.....求楼主给答案.....{:soso_e135:}
作者: gerenvip    时间: 2013-4-12 00:40
对象的初始化过程:
从main函数入口开始,new用到了CodeTest类,所以先把CodeTest.class加载进内存
执行该类的static代码块,所以首先输出 1
在堆内存中开辟空间,分配内存地址。
在堆内存中建立对象的特有属性,并进行默认 初始化
对属性进行显示初始化
对对象进行构造代码块初始化 所以接着输出 2
对对象进行与之对应的构造函数初始化,所示输出 3
将内存地址赋给栈内存中的变量,指向堆内存中的对象。

所以输出顺序是1 2 3
作者: 黑马伍哲沂    时间: 2013-4-12 12:46
李尧 发表于 2013-4-11 23:44
我发现我不会.....求楼主给答案.....

刚开始有人在说err这个错误流,有新开启线程,然后我把程序改成这样:
  1. class TestErr
  2. {
  3.         static
  4.         {
  5.                 System.err.println("1");
  6.         }
  7.         {
  8.                 System.err.println("2");
  9.         }
  10.         public TestErr()
  11.         {
  12.                 System.err.println("3");
  13.         }
  14.         public static void main(String[] args)
  15.         {
  16.                 new TestErr();
  17.         }
  18. }
复制代码
如果真的是开启了新线程的话,这个答案就应该有不确定的顺序输出结果。于是,我去看源代码,发现用的是native方法,所以看不出什么问题。但我反复实验,都是123.这里就出现了两个疑问。
1:这个题目如果单纯考静态、构造代码快和构造函数的执行顺序,干嘛第三个输出语句要用错误流?(可能性是有很多,比如,有人会不认识err,直接说编译错,但觉得真多余了)
2:out和err这两个流,到底有什么区别?
面试的原题,我的理解是答案为123。因为就算开启新线程,没意外的话,也要构造函数执行了之后才开启。
作者: 李尧    时间: 2013-4-12 15:28
黑马伍哲沂 发表于 2013-4-12 12:46
刚开始有人在说err这个错误流,有新开启线程,然后我把程序改成这样:如果真的是开启了新线程的话,这个 ...

我就是不明白这个err流吖,你没改之前的代码,输出结果是不确定的.....我用eclipse测试了.每次运行结果顺序都不一样.
作者: 黑马伍哲沂    时间: 2013-4-12 17:38
李尧 发表于 2013-4-12 15:28
我就是不明白这个err流吖,你没改之前的代码,输出结果是不确定的.....我用eclipse测试了.每次运行结果顺序 ...

啊?  那我也迷惑了。我再试试,我用命令行,运行了几十次了。而且还把三个块里面,分别加了500次循环,全部改成err,也没出现不一样的结果。  这我就真纳闷了,看来要多查资料了。
作者: 黑马伍哲沂    时间: 2013-4-12 18:59
李尧 发表于 2013-4-12 15:28
我就是不明白这个err流吖,你没改之前的代码,输出结果是不确定的.....我用eclipse测试了.每次运行结果顺序 ...

我用eclipse测试,确实不确定。多次运行,出现的结果暂时发现有123,132,312。132的输出是13在同一行,其它都是单独成行。  再将程序加一部分循环。
  1. class TestErr
  2. {
  3.         static
  4.         {
  5.                 for (int x = 1; x <= 100; x++)
  6.                 {
  7.                         if (x % 20 == 0)
  8.                                 System.out.println();
  9.                         System.out.print("1");
  10.                 }
  11.         }
  12.         {
  13.                 for (int x = 1; x <= 100; x++)
  14.                 {
  15.                         if (x % 20 == 0)
  16.                                 System.out.println();
  17.                         System.out.print("2");
  18.                 }
  19.         }

  20.         public TestErr()
  21.         {
  22.                 for (int x = 1; x <= 100; x++)
  23.                 {
  24.                         if (x % 20 == 0)
  25.                                 System.out.println();
  26.                         System.err.print("3");
  27.                 }
  28.         }

  29.         public static void main(String[] args)
  30.         {
  31.                 new TestErr();
  32.         }
  33. }
复制代码
在eclipse中,3构造函数中下面语句无效:
if (x % 20 == 0)
        System.out.println();
而且输出顺序却似乎固定了,怎么运行都是1和2打印完,才打印3,但格式控制无效。
百度了一些资料,没看到合适的解释。但应该与线程无关。如果你有新的发现,期待分享。
作者: 李尧    时间: 2013-4-12 19:51
黑马伍哲沂 发表于 2013-4-12 18:59
我用eclipse测试,确实不确定。多次运行,出现的结果暂时发现有123,132,312。132的输出是13在同一行,其 ...

查了半天只有下面这种说法比较靠谱,应该不是多线程的问题.
out会缓冲,err是立刻打印.
用标准出错打印出来的东西可以马上显示在屏幕,而标准输出打印出来的东西可能要再积累几个字符才能一起打印出来。如果你在应用中混用标准输出和标准出错System.err打出来的信息常常会跑到System.out信息的前面去。。。
作者: 黑马伍哲沂    时间: 2013-4-12 21:59
李尧 发表于 2013-4-12 19:51
查了半天只有下面这种说法比较靠谱,应该不是多线程的问题.
out会缓冲,err是立刻打印.
用标准出错打印出来 ...

看来只能这么理解了。我找到的http://www.cjsdn.net/post/print?bid=1&id=5241意思和这也差不多。




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