try catch finallyとreturnの間の順序の葛藤

5228 ワード

return文のtry-catch-finallyでの実行順序
一般的な状況:
public class TryCatchReturn {	

	public static void main(String[] args) {		
		TryCatchReturn tcr = new TryCatchReturn();
		System.out.println("tcr.test(): "+tcr.test());
	}
	
	public int test(){
		int a = 0;
		
		try{
			System.out.println("a: "+a);
			a = 110;
		}catch(Exception e){
			a = a+3;			
		}finally{
			a ++;
			System.out.println("finally a: "+a);
		}
		return a;     
	}	
}

実行結果:
a: 0finally a: 111tcr.test(): 111
 
1.まず3ブロックのreturnの優先度をテストする
public class TryCatchReturn {	

	public static void main(String[] args) {		
		TryCatchReturn tcr = new TryCatchReturn();
		System.out.println("tcr.test(): "+tcr.test());
	}
	
	public int test(){
		int a = 0;
		
		try{
			System.out.println("a: "+a);
			a = 110;
			return a;
		}catch(Exception e){
			a = a+3;
			return a;
			
		}finally{                 // : finally block does not complete normally 
			a ++;
			System.out.println("finally a: "+a);
			return a;			
		}
		//return a;                                                // , ! 
	}	
}

実行結果:
a: 0finally a: 111tcr.test(): 111
 
test()メソッドはfinallyモジュールのreturn文から最後に返されることがわかる.
 
結論:
1.finallyモジュールは常に実行され、finallyモジュールのreturnも常に実行されるが、tryモジュールのreturnは実行されていないとみなすことができる.
2.finallyモジュール内でreturnを推奨しない;
 
 
2.finallyブロックにreturnがない場合の戻り順をテストする.
public class TryCatchReturn {	

	public static void main(String[] args) {		
		TryCatchReturn tcr = new TryCatchReturn();
		System.out.println("tcr.test(): "+tcr.test());
	}
	
	public int test(){
		int a = 0;
		
		try{
			System.out.println("a: "+a);
			a = 110;
			return a;
		}catch(Exception e){
			a = a+3;
			return a;  
		}finally{
			a ++;
			System.out.println("finally a: "+a);	
		}     
	}	
}

実行結果:
a: 0finally a: 111tcr.test(): 110
 
test()メソッドでは、tryモジュールのreturn文はfinallyモジュールより先に実行されるが、returnはすぐに戻るのではなく、実行後、関数スタックに戻り、finallyモジュールの実行が完了するとtryモジュールのreturn文に戻り、メソッドを終了し、実行を完了する.従って、この場合、tryモジュールのreturn文はfinallyモジュールより先に実行されると考えられるが、メソッドは最終的にreturn文から終了を返す.
 
結論:
1.tryまたはcatchブロックにreturn文がある場合、finallyモジュールの文は実行されます.
2.tryまたはcatchモジュールにreturn文がある場合、finallyモジュールにreturnがない場合、tryまたはcatchモジュールのreturn戻り値はfinallyモジュールの実行前に決定され、return文はfinallyモジュールより先に実行される.
3.returnがtry-catch-finally文の後にある場合、finallyモジュールはreturnの前に実行される.(最初の例のように)
 
3.catchモジュールの介入時のreturnの戻り順をテストする(finallyはreturnがない).
public class TryCatchReturn {	

	public static void main(String[] args) {		
		TryCatchReturn tcr = new TryCatchReturn();
		System.out.println("tcr.test(): "+tcr.test());
	}
	
	public int test(){
		int a = 0;
		
		try{
			System.out.println("a: "+a);
			a = 110;
			throw new Exception();                //try return,unreachable
		}catch(Exception e){
			a = a+3;
			return a;			
		}finally{
			a ++;
			System.out.println("finally a: "+a);
		}     
	}	
}

実行結果:
a: 0finally a: 114tcr.test(): 113
 
test()はcatchモジュールのreturn文から返され、実行プロセスはテスト2に類似しており、finallyモジュールはcatchモジュールのreturn実行前に実行され、catchモジュールのreturn戻り値はfinallyモジュール実行前に決定される.
 
4.catchモジュールの介入時のreturnの戻り順序(finallyにreturnがある)をテストする.
public class TryCatchReturn {	

	public static void main(String[] args) {		
		TryCatchReturn tcr = new TryCatchReturn();
		System.out.println("tcr.test(): "+tcr.test());
	}
	
	public int test(){
		int a = 0;
		
		try{
			System.out.println("a: "+a);
			a = 110;
			throw new Exception();                //try return,unreachable
		}catch(Exception e){
			a = a+3;
			return a;			
		}finally{
			a ++;
			System.out.println("finally a: "+a);
                                                return a;		
}     
	}	
}

実行結果:
a: 0finally a: 114tcr.test(): 114
 
test()はfinallyモジュールのreturn文から返され、catchモジュールのreturnは実行されていないとみなされ、最終的にfinallyモジュールaの値が返される.
 
 
 
4.まとめ
1.例外があるかどうかにかかわらず、finallyブロックの文はtryまたはcatchモジュールにreturnがあるかどうかにかかわらず実行されます.
2.finallyモジュールにreturnがある場合、tryまたはcatchモジュールにreturnがあるかどうかにかかわらず、プログラムセグメントは最終的にfinallyのreturnから返される.
しかし、finally文ではreturnは一般的に推奨されません.
3.finallyモジュールにreturnがない場合、return文はfinallyモジュールより先に実行され、tryまたはcatchモジュールのreturn戻り値(returnがある場合)はfinallyモジュールの実行前に決定されますが、方法は最終的にreturn文から返されます.
 
4.try-catch-finally文の後のreturn文の場合、finallyモジュールはreturnの前に実行され、return戻り値はfinallyモードの実行後に決定される.