java異常處理相關 (2)

來源:互聯網
上載者:User

轉自:http://blog.csdn.net/ZangXT/archive/2009/05/21/4206672.aspx
標題:finally是肯定會執行的!
try/catch/finally語句下,finally子句是肯定會執行的。但是很多人做不同的測試,卻得出了不同的結論。
具體的原理最好是去看《深入java虛擬機器》,裡面對jsr、ret等幾個指令做了詳細的說明。這裡不深入分析,而僅僅是從表現形式上看一下finally的特徵。

代碼:
/*
 * author: Zang XT
 */
public class TestFinally {

 public static void main(String[] args) {

  System.out.println("test1:" + testFinal1());

  System.out.println("test2:" + testFinal2());

  System.out.println("test3:" + testFinal3());

  System.out.println("test4:" + testFinal4());

 }

 static int testFinal1() {
  int i = 1;
  try {
   return i;
  } finally {
   System.out.println("in testFinal1():finally 肯定會被執行的!");
   i = 48;
  }
 }

 static String testFinal2() {
  String str = "try";
  try {
   return str;
  } finally {
   System.out.println("in testFinal2():finally 肯定會被執行的!");
   str = "finally";
  }
 }

 static StringBuilder testFinal3() {
  StringBuilder build = new StringBuilder("try ");
  try {
   return build;
  } finally {
   System.out.println("in testFinal3():finally 肯定會被執行的!");
   build.append("finally");
   build = new StringBuilder("你猜我是誰!");
  }
 }

 static String testFinal4() {
  try {
   return "return in try";
  } finally {
   System.out.println("in testFinal4():finally 肯定會被執行的!");
   return "return in finally";
  }
 }
}

輸出是:
in testFinal1():finally 肯定會被執行的!
test1:1
in testFinal2():finally 肯定會被執行的!
test2:try
in testFinal3():finally 肯定會被執行的!
test3:try finally
in testFinal4():finally 肯定會被執行的!
test4:return in finally

結論很明顯,finally的語句確實執行了,而且肯定是在方法return之前執行的,而且,如果finally中有return語句的話,方法直接結束。這裡需要注意的只有一點:在try中的return語句會將返回結果值壓棧,然後轉入到finally子過程,等到finally子過程執行完畢之後(沒有return),再返回。

下面具體看4個例子:
在testFinal1()中,return i;會將結果i的值,也就是1壓入棧。即使在finally中將i修改了(i=48),也不回對已經壓入棧裡的1造成任何影響。

在testFinal2()中,return str;將str的內容壓入棧,比如我們假設str的內容為0x108(只是一個地址值),通過這個地址值我們能找到"try",那棧裡的內容就是0x108。執行str = "finally",這時候str這個變數的內容可能變為0x237了,這是串"finally"的地址。方法調用結束後,返回的是什嗎?return時壓入棧裡的0x108。所以在列印結果時,我們列印的是通過0x108找到的字串"try"。

在testFinal3()中,return 壓棧的是build這個變數的值,比如是0x3579,通過這個值我們可以找到StringBuilder對象。finally語句塊中對這個對象的內容進行了修改。build = new StringBuilder("你猜我是誰!");讓build變數指向了一個新的對象,這時候build的值可能是0x4579了。但是,別忘了,原來的StringBuilder對象仍然在0x3579處,而我們壓棧的正是0x3579啊!方法返回後,我們得到的傳回值0x3579,通過這個引用值找到相應的StringBuilder對象,所以列印的結果是test3:try finally。

在testFinal4()中,finally有return語句,直接返回,方法結束。

    為什麼不同的人有不同的結論?關鍵是沒有正確理解壓棧的是什麼東西。其實初學java的時候,如果理解了變數是什麼,並區分引用和對象本身就不會得到錯誤的結論了。再有,如果理解java中,方法調用都是採用傳值模式的話,這裡也就類似的可以明白了。 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.