package com;public class TestTryCatch { public static void main(String args[]){
System.out.println(kkk());
}

public static int kkk(){
int k = 0;
try {
k += 2;
return k;
} catch(Exception e){
k++;
return k;
} finally {
k += 5;
}
}
}大家说这个程序的结果会输出什么?开始我认为输出为7,可是实际输出为2,但是经过调试,在程序返回前是要经过k += 5 这段代码的,并且通过观察点k的值是7,但是真正的输出却是2,这是为什么?

解决方案 »

  1.   

    public class TestTryCatch { public static void main(String args[]){ 
    System.out.println(kkk()); 
    } public static int kkk(){ 
    int k = 0; 
    try { 
    k += 2; 
    return k; 
    } catch(Exception e){ 
    k++; 
    return k; 
    } finally { 
    k += 5; 
    return k;



    这样才返回7啊 应该返回值了啊
      

  2.   

    try块没有抛出异常,当执行k += 2;之后就会执行return k; 此时计算出了k的值为2,再执行finally块中代码,但不会影响要返回的值。
    同样 如果try块中是return k+1; 那么结果是3  
      

  3.   

    答:上述代码的含义相当于如下的代码:
    int k = 0; 
    int temp=0;
    try { 
    k += 2; 
    temp=k;  //return k; 
    } catch(Exception e){ 
    k++; 
     temp=k;  //return k; 
    } finally { 
    k += 5; 
    return temp;

      

  4.   

    输出的是kkk()这个整体是2,k=7没有关系
    你这样改下
    public static void main(String args[]){ 
    int i=kkk();
    System.out.println(i); 
      

  5.   


    我想这样也不能说明问题,问题主要是在finally代码块中已经执行了k+=5,这是事实,也就是在方法返回前k已经是7了
      

  6.   

    我也试了下,如果是作为对象返回,如StringBuffer作为返回结果的话,在finally中执行的结果会产生作用,而int型的话,好像就没有发生作用,请高人指点!
      

  7.   

    问:问题主要是在finally代码块中已经执行了k+=5,这是事实,也就是在方法返回前k已经是7了
    答:问题的核心是:方法真正返回的k值,不是你的方法返回前的那个值是7的k.
    记住的是"当时的"原因(即:记住的是当时return的k值),而不是后来的那个k值.
      

  8.   

    答:当然啦.因为这时记住的引用.
    看下例:
    StringBuffer k = new StringBuffer(); 
    try { 
    k.append(2); 
    return k; 
    } catch(Exception e){ 
    k.append(3); 
    return k; 
    } finally { 
    k.append(5);  

    相当于:
    StringBuffer k = new StringBuffer(); 
    StringBuffer temp;
    try { 
    k.append(2); 
    temp=k;  //return k; 此时temp与k指向同一个对象!
    } catch(Exception e){ 
    k.append(3); 
    temp=k;  //return k;temp与k指向同一个对象
    } finally { 
    k.append(5); 
    return temp;  
    //由于temp与k指向同一个对象,对k的对象修改,如:在finally中执行的结果,当然就会产生作用啦.

      

  9.   

    楼上已经说的已经很明显了
    反正不管怎样 我们已经有结论:在try里有return,finally还是会做,也就是说你的程序流程进入到try就一定会执行finally;
    至于造成2这个结果的原因只是finally里并没有return k; 
      

  10.   

    public static int kkk(){ 
    int k = 0; 
    try { 
    k += 2; 
    return k;
    返回的是这个时候的k的值 
    finally 不影响返回的值
      

  11.   

    根据java规范:在try-catch-finally中,如果try-finally或者catch-finally中都有return,则两个return语句都执行并且最终返回到调用者那里的是finally中return的值;而如果finally中没有return,则理所当然的返回的是try或者catch中return的值,但是finally中的代码是必须要执行的。
      

  12.   

    我理解楼主的想法,你是考虑的k值返回之前在内存中已经变成7了,所以你坚持说应该是7。那我告诉你,方法在return的时候并不是把它所拥有的那个值给返回了,而是复制一份返回!因此,对于基本类型的数据,在finally中改变return的值对返回值没有任何影响,而对于引用类型的数据,就有影响。
      

  13.   

    通过看大家的讨论,我似乎明白点了,我们可以把try-catch-finally三块看成一个流水线,分别对同一个资源进行加工。如果中间的某一步(try-catch)遇到return就会冻结这块的执行结果等待返回,至于finally块只是继续前面结果执行做其他操作,不再影响返回前面模块的执行结果,如果这一块代码中有return那么就以这一块的执行结果返回。
      

  14.   


    return 之后的值就是要返回的,往后的finally里面的代码不会改变值
      

  15.   

    public class TestTryCatch { public static void main(String args[]){ 
    System.out.println(kkk());    //4
    } public static int kkk(){  //2
    int k = 0; 
    try {
    k += 2;             
    return k;               //1
    } catch(Exception e){
    k++; 
    return k; 
    } finally {
    k += 5;  //3


    } //1.已经返回给涵数int kkk()了.此时k = 2
    //3接在1执行的.但却没有再把返回给涵数int kkk(),所以kkk()仍然是2
    //4输出当然还是2啊!
      

  16.   

    楼主看来还是不太理解,下面请大家看看这个程序public class Test { /**
     * @param args
     */
    public static void main(String[] args) {

    // 返回值是引用类型
    System.out.println(testReturn01());

    // 返回值是值类型
    System.out.println(testReturn02());

    // 返回值是值类型,在finally中再次修改返回值
    System.out.println(testReturn03());
    }


    public static StringBuilder testReturn01() {
    StringBuilder sb = new StringBuilder("Init");
    try {
    return sb;
    } catch (Exception e) {
    } finally {
    sb.append(" Changed");
    }
    System.out.println("Below Not Execute");
    return sb;
    }

    public static int testReturn02() {
    int i = 2;
    try {
    return i;
    } catch (Exception e) { } finally {
    i += 5;
    }
    System.out.println("Below Not Execute");
    return i;
    }

    public static int testReturn03() {
    int i = 2;
    try {
    return i;
    } catch (Exception e) { } finally {
    i += 5;
    return i;
    }
    }
    }上面程序的输出:
    Init Changed
    2
    7
    通过上面的程序大家要明白一下节点内容:
    1.finally块不管在什么时候都是需要执行的,即使你在try块中return了
    2.return其实就是给函数中的一个隐藏变量赋值(学过vb的同学应该都知道,vb中函数的返回值就是给函数名赋值),
       所以你在try块中return的值会被finally中return的值覆盖掉。
    3.引用类型和值类型的区别,引用类型指向的是同一个对象,一个改变大家都改变。值类型是每个人都有一份大家互不干扰。
    StringBuilder是引用类型,所以在finally中改变的值会影响返回值,int是值类型所以再次改变i的值也不会影响到函数的隐藏变量的值!
    希望对大家的学习有帮助!
      

  17.   


    public static List g(){
    List li = new ArrayList();
    try{
    return li;
    }catch(Exception e){

    }finally{
    li.add("xxxx");
    li = null;
    }
    return null;
    }
    li的值就不是空的!所以不是引用型和原子类型的问题。
      

  18.   


    glacier3 这个提得好,无论是基本类型还是引用类型,return的都是一个temp,基本类型的话。temp保存的是数值,引用类型的话保存的是引用。有错请指教
      

  19.   

    public class t { public static void main(String args[]){ 
    System.out.println(kkk()); 
    } public static int kkk(){ 
    int k = 0; 
    try { 
    k += 2; 
    return k; 
    } catch(Exception e){ 
    k++; 
    System.out.println(k);
    return k; } finally { 
    k += 5; 
    System.out.println(k);


    } try块没有抛出异常,当执行k += 2;之后就会执行return k; 此时计算出了k的值为2,再执行finally块中代码,但不会影响要返回的值。 
    同样 如果try块中是return k+1; 那么结果是3  
    支持二楼的!
      

  20.   

    引用 2 楼 ty_fzpb 的回复:
    try块没有抛出异常,当执行k += 2;之后就会执行return k; 此时计算出了k的值为2,再执行finally块中代码,但不会影响要返回的值。 
    同样 如果try块中是return k+1; 那么结果是3  
     是这个样子地
    不管是否抛出异常finally都会被执行,和返回数据没关系
      

  21.   

    try/catch/finally语句下,finally子句是肯定会执行的。但是很多人做不同的测试,却得出了不同的结论。 具体的原理最好是去看《深入java虚拟机》,里面对jsr、ret等几个指令做了详细的说明。这里不深入分析,而仅仅是从表现形式上看一下finally的特征。代码:
    /* * author: Zang XT */public class TestFinal {    public static void main(String[] args) {        System.out.println("test1:"+testFinal1());        System.out.println("test2:"+testFinal2());        System.out.println("test3:"+testFinal3());        System.out.println("test4:"+testFinal4());    }    static int testFinal1(){        int i = 1;        try{            return i;        }        finally{            System.out.println("in testFinal1():finally 肯定会被执行的!");            i = 48;        }    }    static String testFinal2(){        String str = "try";        try{            return str;        }        finally{            System.out.println("in testFinal2():finally 肯定会被执行的!");            str = "finally";        }    }    static StringBuilder testFinal3(){        StringBuilder build = new StringBuilder("try ");        try{            return build;        }        finally{            System.out.println("in testFinal3():finally 肯定会被执行的!");            build.append("finally");            build = new StringBuilder("你猜我是谁!");        }    }    static String testFinal4(){        try{            return "return in try";        }        finally{            System.out.println("in testFinal4():finally 肯定会被执行的!");            return "return in finally";        }    }}
    输出是:in testFinal1():finally 肯定会被执行的!test1:1in testFinal2():finally 肯定会被执行的!test2:tryin testFinal3():finally 肯定会被执行的!test3:try finallyin testFinal4():finally 肯定会被执行的!test4:return in finally 结论很明显,finally的语句确实执行了,而且肯定是在方法return之前执行的,而且,如果finally中有return语句的话,方法直接结束。这里需要注意的只有一点:在try中的return语句会将返回结果值压栈,然后转入到finally子过程,等到finally子过程执行完毕之后(没有return),再返回。
    下面具体看4个例子:
    在testFinal1()中,return i;会将结果i的值,也就是1压入栈。即使在finally中将i修改了(i=48),也不回对已经压入栈里的1造成任何影响。
    在testFinal2()中,return str;将str的内容压入栈,比如我们假设str的内容为0x108(只是一个地址值),通过这个地址值我们能找到"try",那栈里的内容就是0x108。执行str = "finally",这时候str这个变量的内容可能变为0x237了,这是串"finally"的地址。方法调用结束后,返回的是什么?return时压入栈里的0x108。所以在打印结果时,我们打印的是通过0x108找到的字符串"try"。
    在testFinal3()中,return 压栈的是build这个变量的值,比如是0x3579,通过这个值我们可以找到StringBuilder对象。finally语句块中对这个对象的内容进行了修改。build = new StringBuilder("你猜我是谁!");让build变量指向了一个新的对象,这时候build的值可能是0x4579了。但是,别忘了,原来的StringBuilder对象仍然在0x3579处,而我们压栈的正是0x3579啊!方法返回后,我们得到的返回值0x3579,通过这个引用值找到相应的StringBuilder对象,所以打印的结果是test3:try finally。
    在testFinal4()中,finally有return语句,直接返回,方法结束。
            为什么不同的人有不同的结论?关键是没有正确理解压栈的是什么东西。其实初学java的时候,如果理解了变量是什么,并区分引用和对象本身就不会得到错误的结论了。再有,如果理解java中,方法调用都是采用传值模式的话,这里也就类似的可以明白了。
      

  22.   

    你程序没有异常而且在try里有return,虽然没有异常也会执行finally,但是它里面里面没有return
      

  23.   

    http://www.blogjava.net/liwei/archive/2006/09/13/69437.html
    http://www.blogjava.net/fhtdy2004/archive/2009/04/30/268386.html
    http://old.blog.edu.cn/user1/16293/archives/2006/1248335.shtml
    不知道看不看得懂。
      

  24.   

    public class TestTryCatch { public static void main(String args[]){ 
    System.out.println(kkk()); 
    } public static int kkk(){ 
    int k = 0; 
    try { 
    k += 2; 
    return k; 
    } catch(Exception e){ 
    k++; 
    return k; 
    } finally { 
    k += 5; 
    return k; 



    这位哥们说的不错,就是这样了
      

  25.   

    try块没有抛出异常,当执行k += 2;之后就会执行return k; 此时计算出了k的值为2,再执行finally块中代码,但不会影响要返回的值。 
    同样 如果try块中是return k+1; 那么结果是3  
      

  26.   

    全面测试Java里finally代码对返回值的影响
      

  27.   

    return  不会执行下面的代码了   相当于强行终止!
      

  28.   

      结果是2,在return返回2之后,才执行的finally里面的代码,finally是一个例外,不管怎样它都会执行,除非是断电一类的强行终止,否则,return之后还是会执行的
      

  29.   

       finally的作用就是执行一些必要的代码,比如在程序抛出异常终止后,他还是会执行,所以一般用它来关闭数据库连接等一些必要也很重要的操作.
      

  30.   

    int k = 0; 
    int temp=0; 
    try { 
    k += 2; 
    temp=k;  //return k; 
    } catch(Exception e){ 
    k++; 
    temp=k;  //return k; 
    } finally { 
    k += 5; 
    return temp; 
      

  31.   

      结果是2,在return返回2之后,才执行的finally里面的代码,finally是一个例外,不管怎样它都会执行,除非是断电一类的强行终止,否则,return之后还是会执行的.
       finally的作用就是执行一些必要的代码,比如在程序抛出异常终止后,他还是会执行,所以一般用它来关闭数据库连接等一些必要也很重要的操作.
       综合我上面说的这两点,你可以试一下,不管你是执行try里面的代码,甚至有return,还是执行catch里面的代码,finally都会照常执行.
      只是在我这道题里面,之前已经返回了2,所以函数的返回结果是2,而finally执行后的结果对这个是没有影响的,它是在return之后执行的.
      

  32.   

    如果你把return加到finally里
    那么值就会变为7
      

  33.   

    return  不会执行下面的代码了  相当于强行终止!
      

  34.   

    package com; public class TestTryCatch { public static void main(String args[]){ 
    System.out.println(kkk()); 
    } public static int kkk(){ 
    int k = 0; 
    try { 
    k += 2; 
    return k; 
    } catch(Exception e){ 
    k++; 
    return k; 
    } finally { 
    k += 5; 



    下面是对的,请看:
    package com; public class TestTryCatch { public static void main(String args[]){ 
    System.out.println(kkk()); 
    } public static int kkk(){ 
    int k = 0; 
    try { 
    k += 2; } catch(Exception e){ 
    k++; 
    return k; 
    } finally { 
    k+=5; 

    return k; 

    } 好好比较一下,看看你错在什么地方?
      

  35.   

    三个知识点.
    一个 try-catch-finally(其中finally块用于清除try块中分配的任何资源以及运行任何既使在发生异常时也必须执行的代码.)
    一个 return 问题.
    一个 调试问题.
    综合三者.跟大家指出的问题.LZ应该明白了.
      

  36.   


    try 快里面k += 2 没有报错 遇到了 return k 所以返回了k,下面的代码不执行了,
      

  37.   


    不懂别乱说好不好,finally块里的是必定执行的,无论有没有报错。
      

  38.   

    try {
      ....
    } ctach {
      ....
    } finally {
      ....
    }
    1.finally块肯定要执行
    2.return 返回点的选择楼上很多人说的已经很清楚了,说下自己的看法,不知道大家注意到没有 :try {
     int i = 0;
    } ctach {
      // System.out.println(i); 错误
    }我想表达的意思这是一个“数据堆栈区域的问题”,try ,catch ,finally 分别开辟的是独立的存储区域。
    这样在finally对变量的操作相当是"函数的传参" 这又回归到java的基础,"值传递"的问题,结合return返回点的选择,这样的话是能够很好的解释以上大家遇到的问题。
    不知道自己的想法对不?还希望指点!谢谢
      

  39.   

    呵呵 楼猪的意思是想看看 finally是在什么地方被执行的,try里面return 了一个值,finally肯定会在值出去前执行,不然他就失去意义了。
    再说为什么返回值是2。个人认为,可以这么理解。finally是在return一句执行后,方法栈消失前执行。这样就可以很轻松的解释他返回2。应该在方法栈消失前
    他就返回了一个值。当int等基础类型时返回的是值,当对象时,返回的是地址。所以如果不是int肯定只变了。return时值是没变的,在方法栈消失前被finally改了,且因为返回的是地址,所以外面取的到值自然变化。
      

  40.   

    finally 中无return,所以没有返回。
      

  41.   

    你的那个k+=2后直接就return了 
    所以往下就不走了 
      

  42.   

    这么多人 回答不知道那个是正确的答案了 来个厉害的总结下啊    感觉你问东西有问题  ,,         正常的思维是我们一开始应该觉得是答案是2 ;按照程序的流程走 到return 返回    但finalliy 还要执行   这个大家都清楚。。   然后调试的时候 发现 在return 之前居然K得值变成7了    怎么你倒相反呢 ???
      

  43.   

    个人感觉是值类型和引用类型的区别,以及try catch(异常特征)的特性导致的这个问题
      

  44.   

    不明白啊,是引用的时候为什么list.add("aa");返回的时候把aa带上了,当list=null;就没起作用?
      

  45.   


    String不是基本类型,同样适用~