论坛首页 Java企业应用论坛

finally 浅谈

浏览 9910 次
锁定老帖子 主题:finally 浅谈
该帖已经被评为隐藏帖
作者 正文
   发表时间:2010-07-29  
近日做程序时突发奇想:try ... finally ... 中的 finally 会在返回前执行(在XXX书上看到的,忘了书名了),是于做了以下测试
public class FinallyTest 
{
	public static void main(String args[])
	{
		System.out.println("return: " + new FinallyTest().getString());
	}
	
	public String getString()
	{
		String returnString = null;
		try
		{
			returnString = "this string will be return.";
			return returnString;		
		}finally
		{			
			System.out.println("execute finally...");
			System.out.println("before clean returnString's value: " + returnString);
			returnString = null;
			System.out.println("after  clean returnString's value: " + returnString);
			System.out.println("execute finally end.");
		}		
	}
}

测试结题:
execute finally...
before clean returnString's value: this string will be return.
after  clean returnString's value: null
execute finally end.
return: this string will be return.

如果返回前执行,那么返回的字符串应该为空。但从结果来看,似乎出人的意料之外。
考虑原因:返回前将返回的结果拷贝了。

于是做了以下修改:
public class FinallyTest 
{
	public static void main(String args[])
	{
		System.out.println("return: " + new FinallyTest().getMessage().message);
	}
	
	public Message getMessage()
	{
		Message returnMessage = new Message();
		try
		{
			returnMessage.message = "message";
			return returnMessage;		
		}finally
		{			
			System.out.println("execute finally...");
			System.out.println("before clean returnString's value: " + returnMessage.message);
			returnMessage.message = null;
			System.out.println("after  clean returnString's value: " + returnMessage.message);
			System.out.println("execute finally end.");
		}		
	}
}

class Message
{
	public String message = "message";
}


结果:
execute finally...
before clean returnString's value: message
after  clean returnString's value: null
execute finally end.
return: null

从结果来看,只调用了对象的引用,而对象没有被拷贝。
看来,如所下用 finally 统一处理一般数据类型还是免谈了。
public class FinallyTest 
{
	public static void main(String args[])
	{
		System.out.println("return: " + new FinallyTest().getInt());
	}
	
	public int getInt()
	{
		int returnInt = 0;
		try
		{
			returnInt = 1;
			throw new RuntimeException("...");
		}catch(Exception e)
		{
			returnInt = 2;
			return returnInt;
		}finally
		{			
			System.out.println("execute finally...");
			System.out.println("before switch returnInt's value: " + returnInt);
			switch(returnInt)
			{
				case 1:
					returnInt = 0;
					break;
				case 2:
					returnInt = 3;
					break;
				default:
					returnInt = 4;
			}
			System.out.println("after  switch returnInt's value: " + returnInt);
			System.out.println("execute finally end.");
		}		
	}
}
   发表时间:2010-07-29  
不明白为什么要出现对象拷贝

而你想要的结果又是什么样子的?
0 请登录后投票
   发表时间:2010-07-29  

public class FinallyTest 
{
	public static void main(String args[])
	{
		System.out.println("return: " + new FinallyTest().getString());
	}
	
	public String getString()
	{
		String returnString = null;
		try
		{
			returnString = "this string will be return.";
			return returnString;		
		}finally
		{			
			System.out.println("execute finally...");
			System.out.println("before clean returnString's value: " + returnString);
			returnString = null;
			System.out.println("after  clean returnString's value: " + returnString);
			System.out.println("execute finally end.");
		}		
	}
}


以上一段相当于以下,所以根本没有错。就喜欢简单问题复杂化。

public class FinallyTest 
{
	public static void main(String args[])
	{
		System.out.println("return: " + new FinallyTest().getString());
	}
	
	public String getString()
	{
		String returnString = null;
		try
		{
			returnString = "this string will be return.";
                         System.out.println("execute finally...");
			System.out.println("before clean returnString's value: " + returnString);
			returnString = null;
			System.out.println("after  clean returnString's value: " + returnString);
			System.out.println("execute finally end.");
			return returnString;		
		}finally
		{			
			
		}		
	}
}


0 请登录后投票
   发表时间:2010-07-29  
“返回前将返回的结果拷贝了。” 应该是拷贝了对象的引用
基本数据类型和String的值是不能改变的,基本数据类型和String的值改变后,变量的引用也改变了,但return 返回前的拷贝的引用却没有变,所以 new FinallyTest().getString() 的值是“this string will be return.”
改变Message.message的值对象的引用是没有变化的,所以
new FinallyTest().getMessage().message 返回 null 
0 请登录后投票
   发表时间:2010-07-29   最后修改:2010-07-29
楼主回答有些许问题。。

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



那为什么呢,

return obj;

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

并没有Copy,

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


0 请登录后投票
   发表时间:2010-07-29   最后修改:2010-07-29
可能还是有人看不懂。。
我来说明下。


public class A{
   public String m(){
     //xxxx代码
     
     return obj;// return obj ,只是把obj 指向的地址,交给 returnAddress; finally 里面的代码,在这步后运行
   }
}

//Java会以下面的方式来执行,翻译成下面的


public class A{
   public String m(){
     //xxxx代码
     
     Object returnPointer=obj;// 你看不见的隐式 引用,Java每个方法,都返回一个 返回
     return (String)returnPointer;
   }
}



其实,你的代码相当于


 
 1. public class FinallyTest   
   2. {  
   3.     public static void main(String args[])  
   4.     {  
   5.         System.out.println("return: " + new FinallyTest().getString());  
   6.     }  
   7.       
   8.     public String getString()  
   9.     {  
  10.         String returnString = null;  
  11.         try  
  12.         {  
  13.             returnString = "this string will be return.";  
     ############    String returnPointer=returnString;// 隐式的,看不到。。。。。###################
  14.             return returnPointer;  //##############################        
  15.         }finally  
  16.         {             
  17.             System.out.println("execute finally...");  
  18.             System.out.println("before clean returnString's value: " + returnString);  
  19.             returnString = null;  
  20.             System.out.println("after  clean returnString's value: " + returnString);  
  21.             System.out.println("execute finally end.");  
  22.         }         
  23.     }  
  24. }  


这下,这个方法的返回值,当然不为空了。。。。。。。。。
0 请登录后投票
   发表时间:2010-07-29  
容易误导人,投了隐藏贴。
0 请登录后投票
   发表时间:2010-07-29  

public java.lang.String getString();
  Code:
   0:   aconst_null
   1:   astore_1
   2:   ldc     #48; //String this string will be return.
   4:   astore_1
   5:   aload_1
   6:   astore_3
   7:   getstatic       #16; //Field java/lang/System.out:Ljava/io/PrintStream;
   10:  ldc     #50; //String sss
   12:  invokevirtual   #41; //Method java/io/PrintStream.println:(Ljava/lang/St
ring;)V
   15:  aconst_null
   16:  astore_1
   17:  aload_3
   18:  areturn
   19:  astore_2
   20:  getstatic       #16; //Field java/lang/System.out:Ljava/io/PrintStream;
   23:  ldc     #50; //String sss
   25:  invokevirtual   #41; //Method java/io/PrintStream.println:(Ljava/lang/St
ring;)V
   28:  aconst_null
   29:  astore_1
   30:  aload_2
   31:  athrow

 

	public String getString() {
		String returnString = null;
		try {
			returnString = "this string will be return.";
			return returnString;
		} finally {
			System.out.println("sss");
			returnString = null;
		}
	}
 

 

其实是先返回再执行finally

 

0 请登录后投票
   发表时间:2010-07-29  
yangguo 写道

public class FinallyTest 
{
	public static void main(String args[])
	{
		System.out.println("return: " + new FinallyTest().getString());
	}
	
	public String getString()
	{
		String returnString = null;
		try
		{
			returnString = "this string will be return.";
			return returnString;		
		}finally
		{			
			System.out.println("execute finally...");
			System.out.println("before clean returnString's value: " + returnString);
			returnString = null;
			System.out.println("after  clean returnString's value: " + returnString);
			System.out.println("execute finally end.");
		}		
	}
}


以上一段相当于以下,所以根本没有错。就喜欢简单问题复杂化。

public class FinallyTest 
{
	public static void main(String args[])
	{
		System.out.println("return: " + new FinallyTest().getString());
	}
	
	public String getString()
	{
		String returnString = null;
		try
		{
			returnString = "this string will be return.";
                         System.out.println("execute finally...");
			System.out.println("before clean returnString's value: " + returnString);
			returnString = null;
			System.out.println("after  clean returnString's value: " + returnString);
			System.out.println("execute finally end.");
			return returnString;		
		}finally
		{			
			
		}		
	}
}




如果是这样的话  也不能解释得到的结果吧
0 请登录后投票
   发表时间:2010-07-29  
楼主你试下这个程序看看,看看能不能猜到运行结果。

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();
}
}

}

0 请登录后投票
论坛首页 Java企业应用版

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