1. 程式人生 > >try..catch..finally執行順序return

try..catch..finally執行順序return

new lin name 改變 args catch 而是 變量 see

結論:
1、不管有木有出現異常,finally塊中代碼都會執行;
2、當try和catch中有return時,finally仍然會執行;
3、finally是在return後面的表達式運算後執行的(此時並沒有返回運算後的值,而是先把要返回的值保存起來,管finally中的代碼怎麽樣,返回的值都不會改變,任然是之前保存的值),所以函數返回值是在finally執行前確定的;
4、finally中最好不要包含return,否則程序會提前退出,返回值不是try或catch中保存的返回值。

不管是執行try還是catch,如果所執行的語句中(try和catch中的return只有一個會執行,如果被catch了,肯定是執行catch語句中的return;如果沒有被catch,那肯定是執行try中的return。這裏假設它們中有return,如果沒有return,肯定會執行finally後面的語句)有return語句,則finally之後的語句就不執行(finally裏面的語句肯定還是執行啦);如果是執行try或catch中的語句塊沒有return語句,則finally後面的語句還是會執行的。
舉例:

情況1:try{} catch(){}finally{} return;
顯然程序按順序執行。
情況2:try{ return; }catch(){} finally{} return;
程序執行try塊中return之前(包括return語句中的表達式運算)代碼;
再執行finally塊,最後執行try中return;
finally塊之後的語句return,因為程序在try中已經return所以不再執行。
情況3:try{ } catch(){return;} finally{} return;
程序先執行try,如果遇到異常執行catch塊,
有異常:則執行catch中return之前(包括return語句中的表達式運算)代碼,再執行finally語句中全部代碼,
最後執行catch塊中return. finally之後也就是4處的代碼不再執行。
無異常:執行完try再finally再return.
情況4
:try{ return; }catch(){} finally{return;}
程序執行try塊中return之前(包括return語句中的表達式運算)代碼;
再執行finally塊,因為finally塊中有return所以提前退出。
情況5:try{} catch(){return;}finally{return;}
程序執行catch塊中return之前(包括return語句中的表達式運算)代碼;
再執行finally塊,因為finally塊中有return所以提前退出。
情況6:try{ return;}catch(){return;} finally{return;}
程序執行try塊中return之前(包括return語句中的表達式運算)代碼;
有異常:執行catch塊中return之前(包括return語句中的表達式運算)代碼;
則再執行finally塊,因為finally塊中有return所以提前退出。
無異常:則再執行finally塊,因為finally塊中有return所以提前退出。

最終結論
:任何執行try 或者catch中的return語句之前,都會先執行finally語句,如果finally存在的話。
如果finally中有return語句,那麽程序就return了,所以finally中的return是一定會被return的,
編譯器把finally中的return實現為一個warning。

下面是個測試程序
public class FinallyTest  
{
	public static void main(String[] args) {
		 
		System.out.println(new FinallyTest().test());;
	}

	static int test()
	{
		int x = 1;
		try
		{
			x++;
			return x;
		}
		finally
		{
			++x;
		}
	}
}
結果是2。
分析:
	在try語句中,在執行return語句時,要返回的結果已經準備好了,就在此時,程序轉到finally執行了。
在轉去之前,try中先把要返回的結果存放到不同於x的局部變量中去,執行完finally之後,在從中取出返回結果,
因此,即使finally中對變量x進行了改變,但是不會影響返回結果。
它應該使用棧保存返回值。


C#中 finally 代碼塊裏面不能寫 return 語句 會報錯 控制不能離開finally子句主體


 1 class Program
 2     {
 3         static int test()
 4         {
 5             int x = 1;
 6             try
 7             {
 8                 x++;
 9                 return x;
10             }
11             finally
12             {
13                 ++x;
14                 // return 8;    finally 代碼塊裏面不能寫 return 語句   控制不能離開finally子句主體
15                 // finally總會被執行的  如果在finally裏面執行return,就會把後面代碼遺漏執行。
16             }
17         }
18 
19 
20         static void Main(string[] args)
21         {
22             Console.WriteLine(test());
23         }
24         //在try語句中,在執行return語句時,要返回的結果已經準備好了,就在此時,程序轉到finally執行了。
25         //在轉去之前,try中先把要返回的結果存放到不同於x的局部變量中去,執行完finally之後,在從中取出返回結果,
26         //因此,即使finally中對變量x進行了改變,但是不會影響返回結果。
27         //它應該使用棧保存返回值。
28         //如果finally存在的話。 任何執行try 或者catch中的return語句之前,都會先執行finally語句
29 
30         //        C#有很多不允許:
31         //比如不允許 = 出現在bool表達式裏面:
32         //C++ if (i = 3) // 允許
33         //C# if (i = 3) //不允許
34         //不允許沒有break,比如
35         //C++ case 1: a = 2; case 2 : b = 3; //允許
36         //C# case 1: a = 2; case 2 : b = 3; //不允許
37         //C# case 1: case 2 : b = 3; break; //允許
38         //C#不允許函數沒有返回值,而聲明中有,比如
39         //int func() { return; } //不允許
40 
41         //C#去掉了容易出錯的語法。
42 
43         //        try
44         //{
45         //    FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read);
46         //    StreamReader sr = new StreamReader(fs);
47         //    sr.BaseStream.Seek(0, SeekOrigin.Begin);
48         //    Console.WriteLine("read");
49         //    string temp;
50         //    while ((temp = sr.ReadLine()) != null)
51         //    {
52         //        result.Add(temp);
53         //    }
54         //}
55         //catch (Exception ex)
56         //{
57         //    Console.WriteLine(ex.Message);
58         //}
59         //finally
60         //{
61         //    return result;
62         //}
63 
64 
65 
66         //        try
67         //{
68         //    FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read);
69         //    StreamReader sr = new StreamReader(fs);
70         //    sr.BaseStream.Seek(0, SeekOrigin.Begin);
71         //    Console.WriteLine("read");
72         //    string temp;
73         //    while ((temp = sr.ReadLine()) != null)
74         //    {
75         //        result.Add(temp);
76         //    }
77         //}
78         //catch (Exception ex)
79         //{
80         //    Console.WriteLine(ex.Message);
81         //}
82 
83         //return result;
84 
85         //第二種結構更簡潔、清晰.
86 
87         //frinally一般只做一些清理工作
88         //finally是不管前面如何都會執行的   善後處理
89 
90 
91     }



try..catch..finally執行順序return