论坛首页 Java企业应用论坛

finally 浅谈

浏览 9906 次
锁定老帖子 主题:finally 浅谈
该帖已经被评为隐藏帖
作者 正文
   发表时间:2010-07-30  
public   class   Test22{  
  public   static   void   main(String[]   args){  
  System.out.print(tt());  
  }  
  public   static   int   tt(){  
  int   b   =   23;  
  try{  
  System.out.println("yes");  
  return   b=88;   ***************************************1
  }  
  catch(Exception   e){  
  System.out.println("error   :   "   +   e);  
  }  
  finally{  
  if(b>25){  
  System.out.println("b>25   :   "+b);  
  }  
  System.out.println("finally");  
  }  
  return   b;  
  }  
  }  
   
   
  执行结果:  
  yes  
  b>25   :   88  
  finally  
  88  

执行到1处时, return   b = 88;其实是先执行了b   =   88这个计算,并把计算结果的地址保存在一个临时的局部变量中(应该是把88压入栈),然后开始执行finally子句,finally执行完毕后,再从先前的临时变量中取得返回地址,返回方法的最终结果。根据这样的处理方式,可以试验,当我们试图在finally子句中再行改变b的值时,已经不会对方法的返回结果造成影响。


本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/jhr924/archive/2009/05/22/4207690.aspx
0 请登录后投票
   发表时间:2010-07-30  

下面的程序打印出第一次执行"finally"的深度
打印出来的值是5761、5730、5515,每次结果还都不一样

但是,我觉得,不应该执行finally,因为try还没有执行完,danteng......

public static void main(String[] args) {
		doSomething();
	}
	
	static AtomicBoolean flag = new AtomicBoolean(true);
	static AtomicInteger count = new AtomicInteger(0);
	static void doSomething() {
		//int x = count.get();
		//if(x>100)
		//	return;
		count.incrementAndGet();

		try {
			//System.out.println("try..." + x);
			doSomething();
		}catch(Exception e){
			e.printStackTrace();
		}
		finally {
			if(flag.get()){
			System.out.println("finally" + count.get());
			flag.set(false);
			return;
			}
			
			doSomething();
		}
	}


0 请登录后投票
   发表时间:2010-07-30  
。。。。。
0 请登录后投票
   发表时间:2010-07-30  
fyf_008 写道
楼主回答有些许问题。。

对象绝对没有 Copy. 或者说是克隆。你要用Java,就要知道Java的设计者如何设计java .这问题就解决



那为什么呢,

return obj;

只是 将返回引用(returnPointer),指向了obj 这个引用 指向的对象,

并没有Copy,

虽然,你在 finally 里面,把obj=null;
那只是, obj 这个引用,指向发生了变化,没有影响返回引用(returnPointer)



同意。
在执行到return语句的时候,return的其实是obj的地址。你对指向String的obj来说,任何操作改变的只是obj的指向,而不会改变String的内容。而楼主第二个例子,指向的是一般对象,对obj的改变同时也改变了其初始指向地址空间的值。
个人浅见,说错无怪
0 请登录后投票
   发表时间:2010-07-30  
我只是想知道一下是不是正的如其它人所说任东西需要后期处理的东西(比如数据链接释放之类的)都可以话到 finally 里面去处理。

fyf_008 写道
楼主回答有些许问题。。

对象绝对没有 Copy. 或者说是克隆。你要用Java,就要知道Java的设计者如何设计java .这问题就解决



那为什么呢,

return obj;

只是 将返回引用(returnPointer),指向了obj 这个引用 指向的对象,

并没有Copy,

虽然,你在 finally 里面,把obj=null;
那只是, obj 这个引用,指向发生了变化,没有影响返回引用(returnPointer)




我原以为基本数据类型是以拷贝的形式传回值的(某些书上说的),现在由你这么说我也不知道谁对谁错了,有机会再去了解一个是怎么个传值回来的。

wujiazhao88 写道
楼主你试下这个程序看看,看看能不能猜到运行结果。

public class Danteng{
public static void main(String[] args){
 doSomething();
}

static void doSomething(){

try{
 System.out.println("try...");
 doSomething();
}finally{
System.out.println("finally");
doSomething();
}
}

}




这个问题确实很是 Danteng 1000多次以前都不会执行 finall ,4000次以后才会执行 finally。 这个问题够蛋疼的。
0 请登录后投票
   发表时间:2010-07-30  
public class T{
    public int test(){
        int a=0;
        try{
            return a;
        }finally{
            a++;
        }
        
    }
    
    public static void main(String[] args){
        T t=new T();
        System.out.println(t.test());
    }
}


其中方法test的字节码如下:

public int test();
  Code:
   0:   iconst_0     #0,1:对应int a=0;
   1:   istore_1
   2:   iload_1      #2,3:对应int result=a;
   3:   istore_2
   4:   iinc    1, 1 #4:对应a++
   7:   iload_2      #7,8:对应return result
   8:   ireturn
   9:   astore_3     #9:对应Exception e
   10:  iinc    1, 1 #10:对应a++
   13:  aload_3      #13:,14:对应throw e
   14:  athrow
  Exception table:
   from   to  target type
     2     4     9   any
     9    10     9   any


首先,明确finally干了什么事?
其实class里并没有直接支持finally的机制,编译时finally中的内容会出现在两处地址(以上4行和10行),第一处是在执行try-catch中的代码后,第二次是出现在出现异常时。

其次,怎么返回值
如上2-8行所述,首先是将要返回的值保存在另一个本地变量的位置(istore_2),注意,这个跟a的变量位置1是不同的位置,相当于会先保存需要要返回基本类型的值或者对象的引用到某个变量中,然后再返回这个变量。

结论:所以返回时a的值确实是1,但是返回的并不是a,而是编译器为我们设置隐藏的变量result,其值为0

同理,如果是返回对象,如
public class T{
    public A test(){
        A a=new A();
        try{
            return a;
        }finally{
            a.i++;
        }
        
    }
    
    public static void main(String[] args){
        T t=new T();
        System.out.println(t.test().i);
    }
    
    static class A{
        public int i=0;
    }
}


不妨猜猜会返回多少
0 请登录后投票
   发表时间:2010-07-30  
drift_ice 写道
public class T{
    public int test(){
        int a=0;
        try{
            return a;
        }finally{
            a++;
        }
        
    }
    
    public static void main(String[] args){
        T t=new T();
        System.out.println(t.test());
    }
}


其中方法test的字节码如下:

public int test();
  Code:
   0:   iconst_0     #0,1:对应int a=0;
   1:   istore_1
   2:   iload_1      #2,3:对应int result=a;
   3:   istore_2
   4:   iinc    1, 1 #4:对应a++
   7:   iload_2      #7,8:对应return result
   8:   ireturn
   9:   astore_3     #9:对应Exception e
   10:  iinc    1, 1 #10:对应a++
   13:  aload_3      #13:,14:对应throw e
   14:  athrow
  Exception table:
   from   to  target type
     2     4     9   any
     9    10     9   any


首先,明确finally干了什么事?
其实class里并没有直接支持finally的机制,编译时finally中的内容会出现在两处地址(以上4行和10行),第一处是在执行try-catch中的代码后,第二次是出现在出现异常时。

其次,怎么返回值
如上2-8行所述,首先是将要返回的值保存在另一个本地变量的位置(istore_2),注意,这个跟a的变量位置1是不同的位置,相当于会先保存需要要返回基本类型的值或者对象的引用到某个变量中,然后再返回这个变量。

结论:所以返回时a的值确实是1,但是返回的并不是a,而是编译器为我们设置隐藏的变量result,其值为0

同理,如果是返回对象,如
public class T{
    public A test(){
        A a=new A();
        try{
            return a;
        }finally{
            a.i++;
        }
        
    }
    
    public static void main(String[] args){
        T t=new T();
        System.out.println(t.test().i);
    }
    
    static class A{
        public int i=0;
    }
}


不妨猜猜会返回多少


听君分析豁然开朗。
请教下以下的是用什么来查看的?
public int test();
  Code:
   0:   iconst_0     #0,1:对应int a=0;
   1:   istore_1
   2:   iload_1      #2,3:对应int result=a;
   3:   istore_2
   4:   iinc    1, 1 #4:对应a++
   7:   iload_2      #7,8:对应return result
   8:   ireturn
   9:   astore_3     #9:对应Exception e
   10:  iinc    1, 1 #10:对应a++
   13:  aload_3      #13:,14:对应throw e
   14:  athrow
  Exception table:
   from   to  target type
     2     4     9   any
     9    10     9   any

0 请登录后投票
   发表时间:2010-07-30  
joknm 写道
drift_ice 写道
public class T{
    public int test(){
        int a=0;
        try{
            return a;
        }finally{
            a++;
        }
        
    }
    
    public static void main(String[] args){
        T t=new T();
        System.out.println(t.test());
    }
}


其中方法test的字节码如下:

public int test();
  Code:
   0:   iconst_0     #0,1:对应int a=0;
   1:   istore_1
   2:   iload_1      #2,3:对应int result=a;
   3:   istore_2
   4:   iinc    1, 1 #4:对应a++
   7:   iload_2      #7,8:对应return result
   8:   ireturn
   9:   astore_3     #9:对应Exception e
   10:  iinc    1, 1 #10:对应a++
   13:  aload_3      #13:,14:对应throw e
   14:  athrow
  Exception table:
   from   to  target type
     2     4     9   any
     9    10     9   any


首先,明确finally干了什么事?
其实class里并没有直接支持finally的机制,编译时finally中的内容会出现在两处地址(以上4行和10行),第一处是在执行try-catch中的代码后,第二次是出现在出现异常时。

其次,怎么返回值
如上2-8行所述,首先是将要返回的值保存在另一个本地变量的位置(istore_2),注意,这个跟a的变量位置1是不同的位置,相当于会先保存需要要返回基本类型的值或者对象的引用到某个变量中,然后再返回这个变量。

结论:所以返回时a的值确实是1,但是返回的并不是a,而是编译器为我们设置隐藏的变量result,其值为0

同理,如果是返回对象,如
public class T{
    public A test(){
        A a=new A();
        try{
            return a;
        }finally{
            a.i++;
        }
        
    }
    
    public static void main(String[] args){
        T t=new T();
        System.out.println(t.test().i);
    }
    
    static class A{
        public int i=0;
    }
}


不妨猜猜会返回多少


听君分析豁然开朗。
请教下以下的是用什么来查看的?
public int test();
  Code:
   0:   iconst_0     #0,1:对应int a=0;
   1:   istore_1
   2:   iload_1      #2,3:对应int result=a;
   3:   istore_2
   4:   iinc    1, 1 #4:对应a++
   7:   iload_2      #7,8:对应return result
   8:   ireturn
   9:   astore_3     #9:对应Exception e
   10:  iinc    1, 1 #10:对应a++
   13:  aload_3      #13:,14:对应throw e
   14:  athrow
  Exception table:
   from   to  target type
     2     4     9   any
     9    10     9   any



javap -c xxx
1 请登录后投票
   发表时间:2010-07-30  
我觉得这是jdk设计者故意设计的,finally 是在try 和 catch 返回之前做,但返回的值已经被提前保存了,所以会出现这种情况,这就说明jdk是传值而非引用,如果是引用就不会有这个问题。
0 请登录后投票
   发表时间:2010-07-30  
hardPass 写道

下面的程序打印出第一次执行"finally"的深度
打印出来的值是5761、5730、5515,每次结果还都不一样

但是,我觉得,不应该执行finally,因为try还没有执行完,danteng......

public static void main(String[] args) {
		doSomething();
	}
	
	static AtomicBoolean flag = new AtomicBoolean(true);
	static AtomicInteger count = new AtomicInteger(0);
	static void doSomething() {
		//int x = count.get();
		//if(x>100)
		//	return;
		count.incrementAndGet();

		try {
			//System.out.println("try..." + x);
			doSomething();
		}catch(Exception e){
			e.printStackTrace();
		}
		finally {
			if(flag.get()){
			System.out.println("finally" + count.get());
			flag.set(false);
			return;
			}
			
			doSomething();
		}
	}




别蛋疼了,退出不一定要return,抛异常而已可以。这里有StackOverflowError出现,finally当然会执行。
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics