package com.exception.test;public class test {
public static void main(String[] args)
{
TT ttt=t();
System.out.println(ttt);
System.out.println("a:"+ttt.a+" b:"+ttt.b);
}
public static class TT
{
public int a;
public int b;
public TT(int a,int b)
{
this.a=a;
this.b=b;
}
}
public static TT t()
{
TT ttt=new test.TT(1,2);
String tt=new String("try");
try{
System.out.println(ttt);
return ttt;
}catch(Exception e)
{
System.out.println("catch");
}finally{
ttt=new test.TT(11,22);
ttt.b=222;
System.out.println(ttt);
System.out.println("do finally");
}
return ttt;
}
}为什么在finally里对ttt的修改无效呢?
如果单纯的修改ttt的成员又可以呢?
能具体解析下fianlly代码块里是怎么执行和原理吗?java

解决方案 »

  1.   

    return 时,returen的对象已经保存在一个临时的值里 ,然后执行finally,执行完后返回这个临时值。所以是不会影响的。
      

  2.   

    但是不使用这句ttt=new test.TT(11,22);
    直接使用这句ttt.b=222;却可以改变返回值呢?
      

  3.   

    你看下打印出来的object就知道原因了。public class test {
    public static void main(String[] args) {
    TT ttt = t();
    System.out.println(ttt);//3
    System.out.println("a:" + ttt.a + " b:" + ttt.b);
    } public static class TT {
    public int a;
    public int b; public TT(int a, int b) {
    this.a = a;
    this.b = b;
    }
    } public static TT t() {
    TT ttt = new test.TT(1, 2);
    try {
    System.out.println(ttt);//1
    return ttt;
    } catch (Exception e) {
    System.out.println("catch");
    } finally {
    System.out.println("do finally");
    ttt = new test.TT(11, 22);
    ttt.b = 222;
    System.out.println(ttt);//2
    }
    return ttt;
    }
    }
    com.withiter.csdn.test.test$TT@58d9660d //1
    do finally
    com.withiter.csdn.test.test$TT@28bb0d0d //2
    com.withiter.csdn.test.test$TT@58d9660d //3
    a:1 b:2可以看到2和3是不同的对象,所以你修改的对象2对3打印没有影响!
      

  4.   

    但是不使用这句ttt=new test.TT(11,22);
    直接使用这句ttt.b=222;却可以改变返回值呢?
    在 新建 第一个的时候 
    TT ttt=new test.TT(1,2);
    ttt 指向的是 new test.TT(1,2)
    如果你在finally 运行
    ttt = new test.TT(11, 22);
    相当于你重新定义了 ttt的指向 现在ttt指向 new test.TT(11, 22)
    所有之后你修改ttt.b = 222; 就等于 吧 new test.TT(11, 22) 的b 改成222.而如果你没有重新定义的话。 
    ttt还是指向new test.TT(1,2)。
    所以你修改 ttt.b 就想相当于修改原地址的 b。 
    所以出来值会变。
      

  5.   

    我知道这两个是不同的对象,但是为什么返回的是第1个呢?
    还有如果没有在finally里new一个新的对象,而直接改第一个对象的值,那返回值改变了,不是很懂其中的原理。
      

  6.   

    但是不使用这句ttt=new test.TT(11,22);
    直接使用这句ttt.b=222;却可以改变返回值呢?
    在 新建 第一个的时候 
    TT ttt=new test.TT(1,2);
    ttt 指向的是 new test.TT(1,2)
    如果你在finally 运行
    ttt = new test.TT(11, 22);
    相当于你重新定义了 ttt的指向 现在ttt指向 new test.TT(11, 22)
    所有之后你修改ttt.b = 222; 就等于 吧 new test.TT(11, 22) 的b 改成222.而如果你没有重新定义的话。 
    ttt还是指向new test.TT(1,2)。
    所以你修改 ttt.b 就想相当于修改原地址的 b。 
    所以出来值会变。
    那是不是就是保存第一个对象的地址在方法栈那里了?
      

  7.   

    根据java的specification   finally{} 内的块总是会被执行的,即使try{} 中return,或者throw any exception
    但如果在try{} 块里return了, JVM必须保持 return的引用,并等待finally{}运行结束后返回这个引用。
    所以finally{}的新建的引用,或重新给引用赋值不会改变返回结果的。
    但因为引用实际上是对象的地址,所以在finally里对应用指向的对象属性进行修改,是能体现在返回结果里的。
    不知道这么说你能明白么。
    说白了就是  26行的return ttt;  运行后JVM 就已经确定了这个方法的返回值,为ttt指向的地址:new test.TT(1, 2)
    所以后续再finally{}里即使你试着给ttt重新分配地址,返回的还是之前26的地址。 但由于finally{} 会在返回前执行,所以当你在finally{}中修改26行的引用指向的对象属性值时,这个修改会在返回值中体现出来。
    理解上诉 你需要了解 按值传递和引用传递的意义。
      

  8.   

    我觉得try catch里的return返回的是值而不是引用,所以finally里改变ttt的引用地址不会影响返回的值,而不改变引用,也就是不new对象,直接改变ttt对象的值 会影响return结果。