黑马程序员技术交流社区

标题: 两道小题,看起来简单,但不一定好理解,一题一分 [打印本页]

作者: 黑马-唐磊    时间: 2013-3-8 10:11
标题: 两道小题,看起来简单,但不一定好理解,一题一分
本帖最后由 黑马-唐磊 于 2013-3-8 10:14 编辑

1.以下代码:编译、运行输入“a”(不含引号),按回车后,系统输出什么?
  1.         public static void main(String[] args) throws Exception{
  2.                 int[] x = {1,2,3,4,5,6};
  3.                 for(int y:x){
  4.                         System.in.read();
  5.                         System.out.println(y);
  6.                 }
  7.         }
复制代码
2.以下代码运行后
A.执行一段时间后报栈溢出。   B.会一直输出“try”。    C.会一直输出“try”和“finally”。    D.会一直输出“try”、“catch”和“finally”
  1. private static void foo() {

  2. try
  3. {
  4.         System.out.println("try");
  5.     foo();
  6. }catch (Throwable e) {
  7.     System.out.println("catch");
  8.     foo();
  9. }finally {
  10.     System.out.println("finally");
  11.     foo();
  12. }
  13. }

  14. public static void main(String[] args) {
  15.     foo();
  16. }
复制代码

作者: 李培根    时间: 2013-3-8 10:26
等待答案,话说两道都没做对
作者: 李培根    时间: 2013-3-8 10:38
本帖最后由 李培根 于 2013-3-8 10:42 编辑

简单修改了下程序,这样应该就明白了,a是一个字符,回车是两个字符   
public static void main(String[] args) throws Exception{
        int[] x = {1,2,3,4,5,6};
        for (int i = 0; i < x.length; i++) {
                InputStream in = System.in;
                System.out.println(in.read());
                System.out.println(i);
        }
}

打印结果:
a
97
0
13
1
10
2

作者: 黑马-唐磊    时间: 2013-3-8 10:43
本帖最后由 黑马-唐磊 于 2013-3-8 10:45 编辑
李培根 发表于 2013-3-8 10:38
简单修改了下程序,这样应该就明白了,a是一个字符,回车是两个字符   
public static void main(String[] ...

嗯,是正确答案 第一题程序运行到System.in.read(); 阻塞,等待用户输入System.in.read()//只是为了控制一个循环,
1、当输入a+回车(/r/n),相当于三次System.in.read(),因此会输出前三个值(1,2,3)2、当再次任意输入一个**+回车(/r/n),
也相当于三次System.in.read(),会输出数组的后三个值(4,5,6)
我们将第一题程序这样改写[code=java]public static void main(String[] args) throws Exception{
       int[] x = {1,2,3,4,5,6};
            for(int y:x){
                System.out.println(System.in.read());
                System.out.println(y);
          }
}结果为:[code=java]97
1
13
2
10
3所以执行System.in.read()方法将从键盘缓冲区读入一个字节的数据,然后返回16位的二进制数据,其低8位为键盘的ASCII码,高8位为0。
a的ASCII码为97,换行\r的ASCII码为13,回车\n的ASCII码为10,从控制台输入a的操作为:输入a然后换行、回车。
作者: 冷叙辰    时间: 2013-3-8 10:45
第二个会一直输出“try”和“finally”。    因为没有异常所以走不到catch
作者: 黑马-唐磊    时间: 2013-3-8 10:47
第二题正在等待18期大神回答
作者: 李培根    时间: 2013-3-8 11:21
o318318o 发表于 2013-3-8 10:45
第二个会一直输出“try”和“finally”。    因为没有异常所以走不到catch

走不到catch是肯定的,看结果finally好像是随机运行……
作者: 贾文泽    时间: 2013-3-8 11:47
李培根 发表于 2013-3-8 11:21
走不到catch是肯定的,看结果finally好像是随机运行……

确定走不到catch?
每一次方法的调用JVM都会为方法分配帧栈,jvm对分配帧栈的层数做了限定,当调用到最大层数前一层时,确保在这之前只有try输出,foo()方法调用下一个foo,这时候会抛出一个StackOverflowError,但是catch中捕获的是throwable,所以这次抛出的这个error并不是结束的,反而catch为其延续了生命周期,当catch中再调用foo()时,这时又会抛出StackOverflowError,这个error从catch中抛出,被System Catch捕获到,System Catch处理调用最后一层的finally语句,在finally中又执行foo()。那必须又要抛出StackOverflowError,在finally里抛出的error成为finally的结束点,最后一层方法出栈,返回到前一层的foo。
      但是确实显示就是没有catch输出,可能是JDK的原因吧。
作者: 谢洋    时间: 2013-3-8 13:54
本帖最后由 谢洋 于 2013-3-8 13:57 编辑
  1. <FONT style="BACKGROUND-COLOR: yellow">新发现:
  2. </FONT>public class Test1 {
  3. static int count =0;
  4. public static void main(String[] args) throws InterruptedException {
  5. Thread.sleep(1500);
  6. run();
  7. }
  8. private static void run() throws InterruptedException {
  9. try {
  10. count++;
  11. System.out.println("try--"+count);
  12. run();
  13. }
  14. catch (Throwable e) {
  15. System.out.println("catch");
  16. run();
  17. }
  18. finally {
  19. System.out.println("finally");
  20. run();
  21. }
  22. }
  23. }
复制代码
上面上我改写的测试代码,发现不管是否是同一份.class文件,finally都是在try被打印3500多次后,才被打印的,
而且即使是同一份class,第几次开始打印finally也是不确定,但每次开始被打印都是3500多次时被打印
测试给果n多次的测试结果用横线隔开的是同一份class的多次执行的不同结果,还有一些finally换行,一些不换行 ;坐等大神来解答
-------------------
try--3509
try--3510
try--3511
try--3512
try--3513finallyfinally
try--3514finallyfinally
try--3515
try--3516finallyfinally
try--3517finallyfinally
try--3518
try--3519
-----------------------
try---3548
try---3549finallyfinally
try---3550finallyfinally
try---3551

try---3547
try---3548finallyfinally
try---3549finallyfinally
try---3550

try---3560
try---3561finallyfinally
try---3562finallyfinally
try---3563
try---3651
try---3652
try---3653finallyfinally
try---3654finallyfinally
try---3655
try---3656finallyfinally
try---3657finallyfinally
---------------------------
try-3548
try-3549finallyfinally
try-3550finallyfinally
try-3551
try-3552finallyfinally
try-3553finallyfinally
try-3544
try-3545finallyfinally
try-3546finallyfinally
try-3547
try-3548finallyfinally
try-3549finallyfinally
-------------------------
try--3557
try--3558
finally
finally
try--3559
finally
finally

作者: 贾文泽    时间: 2013-3-8 16:27
李培根 发表于 2013-3-8 11:21
走不到catch是肯定的,看结果finally好像是随机运行……

看了点资料,发现一个很有意思的问题,哈哈
在那个foo方法下面加一个无关紧要的方法,但是这个方法要抛异常,比如

public static void foo1() throws Exception{
        throw  new  Exception("我抛");
}

就这么一写,也不调用,但是整个程序结果就变了,本来是不会输出catch,这么一写就输出了,,,

作者: jonn    时间: 2013-3-8 17:10
第二期貌似递归调用....,在不同的jdk,不同的电脑配置,运行结果不所不同
层层递归,栈深入不断增加,一旦到达mian线程栈深度末尾,会抛出stackoverflowerror ....,try语句块结束点遇到抛出异常,提前通知JVM 调用 finally语句块,finally语句未结束标识,又会去调用try语句,就一直这样循环执行....貌似写这样的程序真没意义...
输出的结果  可能是 try try 。。。。。finally  也可能是 try try catch finally。。。。。
若代码中添加一个方法
  public static void code() throws Exception{
    throw new Exception("code()");
  }
输出结果可能让人更加意外, try try catch finally finally。。。。。。

作者: 谢洋    时间: 2013-3-8 18:18
贾文泽 发表于 2013-3-8 16:27
看了点资料,发现一个很有意思的问题,哈哈
在那个foo方法下面加一个无关紧要的方法,但是这个方法要抛异 ...

catch本来就是为了捕获补try抛出的异常,你都直接抛异常了,那肯定会被catch捕获的
作者: 黑马李磊    时间: 2013-3-8 18:29
好吧,我来学习学习
作者: 贾文泽    时间: 2013-3-8 19:19
谢洋 发表于 2013-3-8 18:18
catch本来就是为了捕获补try抛出的异常,你都直接抛异常了,那肯定会被catch捕获的 ...

但是没有调用那个方法啊。。
作者: 谢洋    时间: 2013-3-8 19:33
贾文泽 发表于 2013-3-8 19:19
但是没有调用那个方法啊。。

其实我并不是很明白你的意思,能把代表你意思的代码完整贴出来?
作者: 贾文泽    时间: 2013-3-8 19:45
本帖最后由 贾文泽 于 2013-3-8 19:46 编辑
谢洋 发表于 2013-3-8 19:33
其实我并不是很明白你的意思,能把代表你意思的代码完整贴出来?

  1. class test{

  2.         private static void foo() {

  3.                 try{
  4.                         System.out.println("try");
  5.                         foo();
  6.                 }catch (Throwable e) {
  7.                         System.out.println("catch");
  8.                         foo();
  9.                 }finally {
  10.                         System.out.println("finally");
  11.                         foo();
  12.                 }
  13.         }
  14.         public static void foo1()throws Exception{        //这个方法并没有调用
  15.                 throw new Exception("*****************");
  16.         }

  17.         public static void main(String[] args) {
  18.                 foo();

  19.         }
  20. }
复制代码

作者: 许鑫星    时间: 2013-3-8 19:55
贾文泽 发表于 2013-3-8 19:19
但是没有调用那个方法啊。。

其实这里用Throwable似乎是抓不到异常的,在这里直接用StackOverflowError来抓就可以看到catch的执行,至于为什么父类的Throwable抓显示不出catch的结果就不知道了,不过用StackOverflowError抓了之后就能看出在栈溢出之后程序在try catch finally catch之间循环,所以那道题估计应该是进不去catch的,只是在栈溢出之后再try finally之间循环
作者: 贾文泽    时间: 2013-3-8 19:59
许鑫星 发表于 2013-3-8 19:55
其实这里用Throwable似乎是抓不到异常的,在这里直接用StackOverflowError来抓就可以看到catch的执行,至 ...

那为什么在foo方法下面加个不相关的方法就能打印出catch了呢?
试试我在16楼发的代码
作者: 猫腻    时间: 2013-3-8 20:00
异常没处理好,有欠缺。
作者: 许鑫星    时间: 2013-3-8 20:14
贾文泽 发表于 2013-3-8 19:59
那为什么在foo方法下面加个不相关的方法就能打印出catch了呢?
试试我在16楼发的代码 ...

我试了,在foo方法里只要做了除输出以外的其他事就会抓到catch,所以最大的可能是就输出方法来说,在栈溢出进入catch时,print这个方法已经执行不了,进而就直接去执行finally了,这也就是为什么没有catch的时候会在try后面跟着两个finally 一个是try里的,一个是catch里的, - -这个问题就很深奥了,只有一个方法的时候也许虚拟机会把所有空间都给他,但是有了其他方法就会流出一些弹性的空间来允许他们自由分配,于是就还能输出catch。。。我是这么猜测的。。。。
作者: 王亚东    时间: 2013-3-8 21:01
会一直输出try和finally,好像每个try都对应一个必须执行的finally(楼上有人解释了catch不到),然后我模拟了只执行1000次try,结果也执行1000次finally。
如果把if中return去掉,楼上也有人测试过了,在大约3000次的时候,开始执行finally,而fianlly中又有foo方法,继续try finally循环,当然try也继续,如下图:

  1. public class Demo03 {
  2. static int i = 0;
  3. static int j = 0;

  4. public static void foo(){
  5. i++;
  6. if(i>1000){
  7. System.out.println("----------------- "+i);
  8. //return;
  9. }
  10. try{
  11. System.out.println("try "+ i);

  12. foo();
  13. }catch(Throwable e){
  14. System.out.println("catch " + i);
  15. }finally{
  16. j++;
  17. System.out.println("finally "+j);
  18. foo();
  19. }

  20. }
  21. public static void main(String[] args) {
  22. foo();
  23. }
  24. }
复制代码

1.jpg (7.61 KB, 下载次数: 8)

1.jpg

作者: 谢洋    时间: 2013-3-8 21:59
贾文泽 发表于 2013-3-8 19:45

的确是这样,但不怎么会这样子




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