public class test_try {
public int doPrint(){
int a = 0;
try{
a=1;
throw new SQLException();
}
catch(Exception e){
System.out.println("catch_开始");
return a;

}
finally{
System.out.println("finally_开始"+a);
a=3;
System.out.println("finally_完毕"+a);
}
}
public static void main(String[] args) {
test_try t=new test_try();
System.out.println("得到返回的值"+t.doPrint());
}}得到的结果是:
              catch_开始
              finally_开始1
              finally_完毕3
             得到返回的值1一般情况下是先执行TRY里面的语句 ,当遇到异常后则执行catch里面的代码,然后再执行finally
那么:结果不是这样的显示方式,应该是return返回2后 然后再回来执行finally ,但是这种方式也不可取,很显然根据显示的结果是这样的执行了try 遇到异常执行catch 里面的System.out.println("catch_开始");然后缓存起return a;(这里的a当然是1了)然后执行finally 里面的了~~最后返回 catch里面执行return a;然后输出a  
 这里问题就来了。为什么要这样做???请高手解释下  谢谢

解决方案 »

  1.   

    先执行catch中代码在return之前是先执行finally中代码,顺序就是这样啊
      

  2.   

     你创建了一个t对象,程序走到try里面,抛出一个SQLException异常,因为你捕获了,所以代码走到catch中,结果打印。因为finally一般都是会走的,除非以下几个情况,cpu停止,调用了System.exit(0),或者线程终止了;否则finally的代码是一定会执行的。
      

  3.   

    前两天刚看过类似的贴,顶的很高,LZ可以去看看。我比较认同下面这种说法。
    1.finally块不管在什么时候都是需要执行的,即使你在try块中return了 
    2.return其实就是给函数中的一个隐藏变量赋值,所以你在try块中return的值会被finally中return的值覆盖掉。 
    3.引用类型和值类型的区别,引用类型指向的是同一个对象,一个改变大家都改变。值类型是每个人都有一份大家互不干扰。 
    StringBuilder是引用类型,所以在finally中改变的值会影响返回值,int是值类型所以再次改变i的值也不会影响到函数的隐藏变量的值!http://topic.csdn.net/u/20090305/20/58898020-d677-4f58-be77-b73e978026af.html?17180
      

  4.   

    http://blog.csdn.net/ZangXT/archive/2009/05/21/4206672.aspx
      

  5.   

    方法在return的时候并不是把它所拥有的那个值给返回了,而是复制一份返回!因此,对于基本类型的数据,在finally中改变return的值对返回值没有任何影响,而对于引用类型的数据,就有影响。
      

  6.   

    finally语句是不论什么情况都执行的。return不论放在try里还catch里都是会先执行finally语句,然后在return的。你想想如果先执行return那么这个方法不是跳出去了吗,那它还怎么执行finally语句啊,所以finally语句是会在return执行的。你只要知道,finally语句是不论什么情况都执行的,这一点就容易想名了。
      

  7.   

    不太明白,我debug了一下,return a;执行了两次。就像楼主说的:为什么要这样做??? 
      

  8.   

    finally中的语句是必须要执行的,当try抛出异常并由catch捕获后,就执行catch中的语句,当执行到return语句时以为有finally语句所以会立即返回,当执行完finally后,返回a的值并由方法的调用者接受。更详细的可以参考核心技术中的讲解。
      

  9.   

    LZ “那么:结果不是这样的显示方式,应该是return返回2后 然后再回来执行finally ,但是这种方式也不可取”
    不知道你什么意思,你程序的执行结果是正确的。
      

  10.   

    个人认为楼主的疑问牵涉到两点:
    1、java中的变量问题:
    java中基本类型都是传值,还有一个特殊的对象String对象是不变量,也可以理解为传值吧
    public int doPrint() 这个方法的返回值如果是 基本类型或者是 String类型,起返回结果都是在Catch内确定了,因为finally内
    的修改都是另一个内存区域内的值public Object doPrint() 如果是对象那么java中是传引用,所以finally做的修改跟catch内做的修改是同一块内存中的数据,这个时候finally内修改就会起作用,如果是返回对象的话,就是楼主理解的那样了2、finally 块内语句 除断电,jvm崩溃,或者System.exit() 不会执行到,其他情况都会先执行finally块内的语句,最后执行return语句
    下面是我的测试代码:
    public class Fuck { /**
     * 测试StringBuffer对象
     * 
     * @return
     */
    public static StringBuffer printSB() {
    StringBuffer a = new StringBuffer();
    try {
    a.append("try");
    System.out.println("try_开始" + a);
    throw new Exception();
    } catch (Exception e) {
    a.append("catch");
    System.out.println("catch_开始" + a); return a; } finally {
    a.append("finally");
    System.out.println("finally_开始" + a);
    }
    } /**
     * 测试用户对象
     * 
     * @return
     */
    public static Stu printObj() {
    Stu stu = new Stu(25, "ffshi");
    try {
    stu.setName("try");
    System.out.println("try_开始 " + stu.toString());
    throw new Exception();
    } catch (Exception e) { stu.setName("catch");
    System.out.println("catch_开始 " + stu.toString());
    return stu; } finally {
    stu.setName("finally");
    System.out.println("finally_开始 " + stu.toString()); }
    } public static void main(String[] args) {
    System.out.println(printSB());

    // try_开始try
    // catch_开始trycatch
    // finally_开始trycatchfinally
    // trycatchfinally
     System.out.println(printObj().toString());
    //  try_开始 age:25   name:try
    //  catch_开始 age:25   name:catch
    //  finally_开始 age:25   name:finally
    //  age:25   name:finally
    }}class Stu {
    @Override
    public String toString() {
    // TODO Auto-generated method stub
    return "age:" + age + "   name:" + name;
    } int age;
    String name; public Stu(int age, String name) {
    this.age = age;
    this.name = name;
    } public int getAge() {
    return age;
    } public void setAge(int age) {
    this.age = age;
    } public String getName() {
    return name;
    } public void setName(String name) {
    this.name = name;
    }}
      

  11.   

    执行顺序:
    1.执行try里面的语句,
    2.如果有异常执行catch语句,注意如果catch中有return语句,应该先执行finally语句再返回执行return语句。
    3.不管是否有异常,都要执行finally语句所以当前程序的结果很正常!
      

  12.   

    感觉大家的回复都没有回复到问题的点上。。除了6楼   你们都在研究执行顺序,,问题是在 finally 里面  a=3; 既然是先执行这里了,把a的赋值成 3 了 为何结果还是1
      

  13.   

    感觉大家的回复都没有回复到问题的点上。。除了6楼   你们都在研究执行顺序,,问题是在 finally 里面  a=3; 既然是先执行这里了,把a的赋值成 3 了 为何结果还是1
      

  14.   

    我的理解是 : catch里return a; 程序运行到这里,应该JVM已经取了a里面的值,只是没有执行return 操作,就去执行finally块,执行完finally块,直接return了,没有再去读取a里面的值。
      

  15.   

    其实很简单,捕获了异常之后执行了Catch,将1推入了main方法的栈,但代码并没有回到main方法去执行而执行了紧跟Catch的Finally代码块,变量a的值改变,但main方法的栈顶还是1,所以就得到的楼主的结果了。
      

  16.   

    你在Finally中也应该加句 return a 试试。
      

  17.   

    是这样运行啊
    除非 突然掉电,系统崩溃或JVM崩溃,调用到system.exit.不然是不可能不执行finally
      

  18.   

    一般情况下,finally是无论如何都要执行的,如果finally中有返回,那么不管有没有异常,最终返回的finally中的值!
      

  19.   

    一般情况下,finally是无论如何都要执行的,如果finally中有返回,那么不管有没有异常,最终返回的finally中的值! 
      

  20.   

    同意16楼的看法。我认为正确的代码应该以下。这样返回值就始终是3。
    其实在编程中,finally 一般不要给变量赋值,它的一个主要作用是释放占用的资源。
    public class test_try {
                public int doPrint(){
            int a = 0;
            try{
                a=1;
                throw new SQLException();
            }
            catch(Exception e){
                System.out.println("catch_开始");
                //return a; 不应此处返回
                
            }
            finally{
                System.out.println("finally_开始"+a);
                a=3;
                System.out.println("finally_完毕"+a);
            }
           
            return a; //应此处返回
        }
        public static void main(String[] args) {
            test_try t=new test_try();
            System.out.println("得到返回的值"+t.doPrint());
        }}
      

  21.   

    finally中的语句是必须要执行的,当try抛出异常并由catch捕获后,就执行catch中的语句,当执行到return语句时以为有finally语句所以会立即返回,当执行完finally后,返回a的值并由方法的调用者接受。
      

  22.   

    class test_try {
                public int doPrint(){
            int a = 0;
            try{
                a=1;
                throw new SQLException();
            }
            catch(Exception e){
                System.out.println("catch_开始");
                //return a; 不应此处返回
                
            }
            finally{
                System.out.println("finally_开始"+a);
                a=3;
                System.out.println("finally_完毕"+a);
            }
           
            return a; //应此处返回
        }
        public static void main(String[] args) {
            test_try t=new test_try();
            System.out.println("得到返回的值"+t.doPrint());
        }}
      

  23.   

    跟我们那个考试题差不多啊,我想问的是这里为什么try里面的语句要发生异常呢???
      

  24.   

    不管在什么情况下,捕获到异常还是没捕获到,finally块都是需要执行的,
    在finally中改变return的值对返回值没有任何影响,而对于引用类型的数据,就有影响。
    所以结果a=1
      

  25.   

    我觉得关键看return在哪里,执行顺序大家应该都知道,先try块,catch,finally,之后是catch底下未执行的代码;
    最后的System.err.println是在main里面的,所以打印出来的只是return的值,至于在后面继续改了这个变量,变量
    确实改变了,但你return的不是更改后的值,做了简单两个小测试,大家可以试一下。我用的jdk是1.4.2,
    还有一种说法是因为int型是值类型,用Integer就不一样了,我用String类型同样试了一下,结果还是如此。
    import java.lang.*;
    public class  A
    {
    public static void main(String[] args) 
    {
    A a = new A();
    System.err.println(a.gets());
    }
    public int gets(){
    try{
    throw new Exception();
    }catch(Exception e){
    return 1;
    }finally{
    return 2;
    }
    }
            public int gets2(){
    int i= 2;
    try{
    throw new Exception();
    }catch(Exception e){
    //return 1;
    i=1;
    }finally{
    //return 2;
    i=3;
    }
    return i;
    }
            public String gets3(){
    String i= "a";
    String b="e";
    try{
    throw new Exception();
    }catch(Exception e){
    //return 1;

    i="b";
    return i;
    }finally{
    //return 2;
    i=b;
    }
    //return i;
    }
    }
      

  26.   

    结果是:
    catch_开始
    finally_开始1
    finally_完毕3
    得到返回的值1如果改为
    public class test_try {
                public int doPrint(){
            int a = 0;
            try{
                a=1;
                throw new SQLException();
            }
            catch(Exception e){
                System.out.println("catch_开始");
                return a;
                
            }
            finally{
                System.out.println("finally_开始"+a);
                a=3;
                System.out.println("finally_完毕"+a);
                return a;
            }
        }
        public static void main(String[] args) {
            test_try t=new test_try();
            System.out.println("得到返回的值"+t.doPrint());
        }}结果是:
    catch_开始
    finally_开始1
    finally_完毕3
    得到返回的值3
    分析下……
      

  27.   

    这好像没什么好难理解的啊当给a赋值为3事,早就return了a(a=1)
      

  28.   

    其实finally中并没有隐含的包括一个return方法,所以这里值的改变并没有影响
      

  29.   

    ----执行a=1这是必然的吧
    ----catch,前面跑出个异常,所有就要catch一下
    ----return,catch里有return 就要执行阿 返回1
    然后停住去执行finally,注意,返回值已经返回了就是1,不是a
    ----finally,这个必须执行,最后就要执行.
      

  30.   

    ----finally,这个必须执行,最后就要执行.(这里如果有return 那么返回值才会变,给返回值传个变量,返回值是哪个变量的值了,而不是那个变量,这就是传说中的值传递,不是地址传递)