大家看看以下代码:public static String fun(){
String s = "abc";
try{
throw new Exception();
} catch (Exception e) {
return s;
} finally{
s = "s";
}
}你们是怎么样理解的?

解决方案 »

  1.   

    return了再执行finally
    请看代码 static String s = "abc"; public static String fun() {
    try {
    throw new Exception();
    } catch (Exception e) {
    return s;
    } finally {
    s = "s";
    }
    } public static void main(String[] args) throws Exception {
    System.out.println(T1.s);
    System.out.println(T1.fun());
    System.out.println(T1.s);
    }
      

  2.   

    finally中对变量s的修改并不会改变s的原来返回值,s的值还是"abc"
      

  3.   


    static String s = "abc";    public static String fun() {
            try {
                throw new Exception();
            } catch (Exception e) {
                return s;
            } finally {
             System.out.println("in finally");
                s = "s";
            }
        }    public static void main(String[] args) throws Exception {
            System.out.println(Test.s);
            System.out.println(Test.fun());
            System.out.println(Test.s);
        }debug了一下
    发现return是在finally调用之后才执行的
    至于返回的是“abc”就不知道是什么原因了
      

  4.   

    如果一个程序的try{}finally{}内出现了return的时候, jvm会怎么处理呢? 这是面试试题经常会出现的问题. 但是其实可以看到一些很深的东西.一些小程序可以印证我的想法.
    例如下面的程序:package basic;import java.util.HashMap;
    import java.util.Map;public class TryFinal {
    Map<String, String> x = new HashMap<String, String>();
    volatile long dd = 0L;public long returnLong() {
    dd = 99;try {
       dd = 100;
       return dd;
    } finally {
       dd = 88;
    }
    }public Map returnMap() {try {
       x.put("8","8");
       return x;
    } finally {
       //x = new HashMap<String, String>();
       x.put("7", "7");
    }}public static void main(String[] args) {
    TryFinal t = new TryFinal();System.out.println( t.returnLong() ); //输出100System.out.println( t.dd ); //输出88Map m = t.returnMap();System.out.println(m); //输出{7=7, 8=8}
    System.out.println(t.x); //输出{7=7, 8=8}System.out.println(m==t.x); //输出true}
    }
    在这种结构的程序中, 如果返回是基础类型的值, 那么finally中进行的修改是会反映到示例中的值的, 但是却不会影响到方法返回给调用者的结果. 这很好的印证了"java中只有值传递". 调试过程中也发现, 是先执行了return dd; 再跳到finally中执行dd=88; 再跳到 return dd; 所以我大胆的设想,在sun的jvm实现中, 方法内部有一个我们看不到的"返回变量", 在第一次执行return dd;的时候就被赋值为100, 最后返回的自然就是100. 而示例内的dd, 因为被finally段的dd=88;修改了, 自然就保持了88但是如果返回类型是对象类型, 情况又不同. 同样基于上述假设, 调试过程中看到的也是相同的运行过程, 但是这个看不到的"返回变量"却被赋予了真正对象的内存地址, 也就是一串符号表示. 因此, 被返回的Map对象和t对象中引用到的Map对象其实是同一个, 则很明显finally中对Map对象进行的修改就反映在System.out.println(m); //输出{7=7, 8=8}这个输出里面了, 而且最后的一句"System.out.println(m==t.x); //输出true" 也能证明这点.留意这句, //x = new HashMap<String, String>(); 如果把注释去掉, 那么System.out.println(m==t.x); 就输出false了 
      

  5.   

    这是一个测试抛出异常的方法。
        工作原理:在方法体中始终抛出异常,被捕获后执行catch后的代码。可以构造如下类来测试:public class Tester {
    static String s = "abc"; public static String fun() {
    try {
    throw new Exception();
    } catch (Exception e) {
    return s;
    } finally {
    s = "s";
    }
    } public static void main(String[] args) {
    String str = new Tester().fun();
    System.out.println(str);
    }
    }
    运行结果:
    abc
      

  6.   

    请看下面的测试:证明s的值最终改变了
    public class Tester {
    static String s = "abc"; public static String fun() {
    try {
    throw new Exception();
    } catch (Exception e) {
    return s;
    } finally {
    s = "s";
    }
    } public static void main(String[] args) {
    String str = new Tester().fun();
    System.out.println(str);
    System.out.println(s);
    }
    }
    运行结果:
    abc
    s
      

  7.   

    这种解释好像 跟下面的有点 矛盾!public static String fun2(){
    try{
    throw new Exception();
    } catch (Exception e) {
    return "123";
    } finally{
    return "abc";
    }
    }
      

  8.   

    只知道finally用于做出现Exception后的”善后工作“,肯定会被执行。表现在代码中应该是返回s后再执行finally块
      

  9.   

    反正finally最后是会被执行的还有这种写法是不规范的
      

  10.   

    我的理解,return之后不会立刻返回,但这时已指定了返回对象,执行完finally之后再返回
    返回的值是对象"abc" ,s指向了新的值"s"
      

  11.   

    测试代码,在return后停了下来,执行finally后返回static String s = "abc";     public static String fun() {
            try {
                throw new Exception();
            } catch (Exception e) {
             System.out.println("return");
                return s;
            } finally {
         try {
    Thread.sleep(1000);
    } catch (InterruptedException e) {
    e.printStackTrace();
    }
             System.out.println("finally");
                s = "s";
            }
        }     public static void main(String[] args) throws Exception {
         Test T1 = new Test();
            System.out.println(T1.s);
            System.out.println(T1.fun());
            System.out.println(T1.s);
        }打印结果:
    abc
    return
    (有停顿)
    finally
    abc
    s
      

  12.   

    最好不要在finally里写return
    finally一般用作关闭资源 释放资源
      

  13.   

    拜托楼上各位测试的时候别用
    static String s;
    特别是建议不要用static用了static,变量的性质发生了很大的变化
    无法说明楼主的问题吧
      

  14.   

    楼主代码里的
    String s = "abc";
    s 是个局部变量如果你加了static的话
    s就变成了全局的静态变量static的用法不要我说了吧
    在任何一处更改都会受影响如果把这个变量加上static
    那讨论try,catch,finally,有何意义?
    更何况里面还有return
      

  15.   

    请问 局部变量可以用static吗
    而且 在这里 我就是故意改成成员变量来说明问题的
      

  16.   

    我不知道static和try catch finally有什么关系
      

  17.   


    和朋友讨论了一下,似乎应该是这样的程序执行到return s;的时候,只是把返回值放到了方法的调用处
    但是,这个时候方法并没有结束,因为还有finally块没有执行
    也就是说严格的讲finally块应该是在return后面执行的
    但是在finally里面只是给s赋值,所以这个并没有影响到返回值如果,程序变成下面这个样子public static String fun(){
            String s = "abc";
            try{
                throw new Exception();
            } catch (Exception e) {
                return s;
            } finally{
                s = "s";
                return s;
            }
        }那末打印出来的就是 s 了
    因为在finally里面刷新了返回值
      

  18.   

    很简单的道理,try块如果捕获到异常就执行catch里面的内容,否则将跳过直接进入finally块;但finally块无论发生异常与否都会执行的!
      

  19.   

    这说明java是值传递,在到 return s; 时,将s的值拷贝了一份放到的函数的返回值
    而finally总是会被执行,在跳出函数前,finally内的代码得到了执行的机会,从而使 s = "s";另:就算返回类型是对象类型,还是值传递,只不过因为对象变量内放的是引用的地址,返回时是引用的地址的一份拷贝,而不是整个对象实例的拷贝(那变成克隆了)。根据推荐的java规范,一个函数只能有一个retrun,那么显然retrun应该放在“踹开吃”外面,楼主的这种写法是不规范的。
      

  20.   


    public Map returnMap() {
    try {
    x.put("8", "8");
    return x;
    } finally {
    // x = new HashMap <String, String>();
    x.put("7", "7");
    }
    }public String fun(){
            String s = "abc";
            try{
                throw new Exception();
            } catch (Exception e) {
                return s;
            } finally{
                s = "s";
            }
        }public String fun2(){
            try{
                throw new Exception();
            } catch (Exception e) {
                return "123";
            } finally{
                return "abc";
            }
        }
    我的解释是这样:
    String 显然是对象,在catch里碰到了return,此时已经拷贝了String对象的地址到了程序返回的变量(如大伙所说的)
    然后,程序进入了finally 语句块,此时 变量 s 指向了另外一个String对象"s"(原因String是被final修饰的)所以程序返回的变量的值仍然指向 "abc" 的地址。
    对于map的解释:
    因为HashMap是没被final 修饰,
    所以程序返回的变量  与finally里修改的map的实例指向同一个地址。
    所以返回的Map实例是包含了两个键值对.
    对于catch和finally 都有return的情况,我的解释是:当程序跑到catch里的return时,则程序的返回变量的值 此时指向了 当前return的值,然后程序继续执行finally的return,此时程序的返回变量值会覆盖了先前的值,所以程序真正返回 又会是finally里return的值
      

  21.   

    我只记得,try,catch,finally,大家都说finally最终都会执行,但是在多线程有一个方法是会绕过finally的,也就是finally会不执行。【大家可以去找下,我有点忘记了】
      

  22.   

    楼上所说的多线程的情况 指的是jvm运行的线程全是守护线程的情况下 会自动关闭jvm
    守护线程一般是为非守护线程服务的 其他线程关闭了 守护线程也完成工作了 所以开着也没什么用 就关了
    这种设计是很科学的所以不是finally不会执行 而是jvm已经终止了 后面的任何程序段都不会执行
      

  23.   

    try里面放的是有可能出错的代码,
    当执行到这里面时如果有异常则进入catch反之则不会执行catch,
    而finally是不管有没有异常都会执行的代码块。
    在catch已经返回s="abc"
    之后才对s重新赋值
    只有catch中有return
    所以输出的是abc
      

  24.   

    下面的几个输入语句也许能更清楚的展现执行顺序:public class Dummy2 {
    public static void main(String[] args) {
    String str = fun();
    PrintUtil.print("return");
    PrintUtil.print(str);
    }

    public static String fun(){
            String s = "abc";
            try{
                throw new Exception();
            } catch (Exception e) {
                return fun2(s);
            } finally{
                s = "s";
                PrintUtil.print("finally");
            }
        }

    public static String fun2(String s){
    PrintUtil.print("in fun2 s=" +s);
    return s;
    }
    }
    执行结果:
    in fun2 s=abc
    finally
    return
    abc即: 在finally前执行了return语句, 但是并没有真正的返回, 而是去执行了finally, 
    然后再将结果返回.
    于是做了一下更改: 
    1. 将fun2的返回值改为其他值, 则整个fun的返回值等于fun2的返回值
    2. 在finally里添加return语句, 则整个fun的返回值等于finally里的返回值.
      

  25.   

    接受这个解释,如果finally中没有返回语句,不论在finally中做什么修改,都不会影响最后的返回结果。