整體區別java
final 用於申明屬性,方法和類,表示屬性不可變,方法不能夠被覆蓋,類不能夠被繼承。
finally 是異常處理語句結構中,表示老是執行的部分。
finallize 表示是object類一個方法,在垃圾回收機制中執行的時候會被調用被回收對象的方法。容許回收此前未回收的內存垃圾。全部object都繼承了 finalize()方法mysql
一.final詳解程序員
Java中final也用來修飾3類東西:變量,方法和類。
1.變量
final修飾變量表示該變量是不可變的。例如 final int i =1;在程序中i的值就不容許改變了。比較容易混淆的是final用來修飾引用變量時,表示該引用變量是不可變的即引用變量指向的內存地址是不變的,可是被指的內存地址中的類是能夠改變的。例如:
final MyClass myClass = new MyClass();
這樣聲明myClass後,其所指向的內存地址就固定了,但仍然能夠改變myClass所引用對象的成員變量。若是試圖重用myClass這個變量,讓其引用另外一個對象則會出錯。
myClass = new MyClass();//error!!!
2.方法
final修飾方法時表示該方法是不能被子類重寫的。
3.類sql
final修飾類時表示該類是不能被繼承的,因爲java的單繼承關係,因此該類是繼承關係鏈中的終端。數據庫
關於final的幾個注意事項:jvm
a、final變量必須在聲明的時候初始化或是在構造函數中初始化;
b、接口中聲明的全部變量都是final的;
c、final,finally,finalize的區別。final表示不可變,final表示必須執行的語句,finalize表示垃圾回收時執行的代碼。函數
二.finalizespa
Java中全部類都從Object類中繼承finalize()方法。.net
當垃圾回收器(garbage colector)決定回收某對象時,就會運行該對象的finalize()方法。值得C++程序員注意的是,finalize()方法並不能等同與析構函數。Java中是沒有析構函數的。C++的析構函數是在對象消亡時運行的。因爲C++沒有垃圾回收,對象空間手動回收,因此一旦對象用不到時,程序員就應當把它delete()掉。因此析構函數中常常作一些文件保存之類的收尾工做。可是在Java中很不幸,若是內存老是充足的,那麼垃圾回收可能永遠不會進行,也就是說filalize()可能永遠不被執行,顯然期望它作收尾工做是靠不住的。線程
那麼finalize()到底是作什麼的呢?它最主要的用途是回收特殊渠道申請的內存。Java程序有垃圾回收器,因此通常狀況下內存問題不用程序員操心。但有一種JNI(Java Native Interface)調用non-Java程序(C或C++),finalize()的工做就是回收這部分的內存。
三.finally 詳解
Java異常處理模型與其餘語言相比,關鍵詞finally是最出色的新增特性了。finally構件使得該區段中的代碼老是得以執行,而不管是否發生異常,特別適用於維護對象的內部狀態(用來保證異常發生恢復對象的有效狀態,以確保程序能在處理完異常後自動再次投入運行)和清理non-memory資源(垃圾回收機制沒法處理的資源,如數據庫鏈接、Socket等等)。
但有一點值得注意,那就是儘可能不要從try區段中返回(調用return),由於只要有finally區段存在,它就必定會被執行,那麼若是你在finally區段中又調用了一次return語句,則try區段中的返回值將會被遮掩,使得方法調用者獲得的是finally區段中的返回值--這經常又與程序編寫的初衷相背。
首先來問你們一個問題:finally 語句塊必定會執行嗎?
不少人都認爲 finally 語句塊是確定要執行的,其中也包括一些頗有經驗的 Java 程序員。惋惜並不像大多人所認爲的那樣,對於這個問題,答案固然是否認的,咱們先來看下面這個例子。
public class Test { public static void main(String[] args) { System.out.println("return value of test(): " + test()); } public static int test() { int i = 1; // if(i == 1) // return 0; System.out.println("the previous statement of try block"); i = i / 0; try { System.out.println("try block"); return i; }finally { System.out.println("finally block"); } } }
清單 1 的執行結果以下:
the previous statement of try block Exception in thread "main" java.lang.ArithmeticException: / by zero at com.bj.charlie.Test.test(Test.java:15) at com.bj.charlie.Test.main(Test.java:6)
另外,若是去掉上例中被註釋的兩條語句前的註釋符,執行結果則是:
return value of test(): 0
在以上兩種狀況下,finally 語句塊都沒有執行,說明什麼問題呢?只有與 finally 相對應的 try 語句塊獲得執行的狀況下,finally 語句塊纔會執行。以上兩種狀況,都是在 try 語句塊以前返回(return)或者拋出異常,因此 try 對應的 finally 語句塊沒有執行。
那好,即便與 finally 相對應的 try 語句塊獲得執行的狀況下,finally 語句塊必定會執行嗎?很差意思,此次可能又讓你們失望了,答案仍然是否認的。請看下面這個例子(清單 2)。
public class Test { public static void main(String[] args) { System.out.println("return value of test(): " + test()); } public static int test() { int i = 1; try { System.out.println("try block"); System.exit(0); return i; }finally { System.out.println("finally block"); } } }
清單 2 的執行結果以下:
try block
finally 語句塊仍是沒有執行,爲何呢?由於咱們在 try 語句塊中執行了 System.exit (0) 語句,終止了 Java 虛擬機的運行。那有人說了,在通常的 Java 應用中基本上是不會調用這個 System.exit(0) 方法的。OK !沒有問題,咱們不調用 System.exit(0) 這個方法,那麼 finally 語句塊就必定會執行嗎?
再一次讓你們失望了,答案仍是否認的。當一個線程在執行 try 語句塊或者 catch 語句塊時被打斷(interrupted)或者被終止(killed),與其相對應的 finally 語句塊可能不會執行。還有更極端的狀況,就是在線程運行 try 語句塊或者 catch 語句塊時,忽然死機或者斷電,finally 語句塊確定不會執行了。可能有人認爲死機、斷電這些理由有些強詞奪理,沒有關係,咱們只是爲了說明這個問題。
下面,咱們先來看一個簡單的例子(清單 3)。
public class Test { public static void main(String[] args) { try { System.out.println("try block"); return ; } finally { System.out.println("finally block"); } } }
清單 3 的執行結果爲:
try block finally block
清單 3 說明 finally 語句塊在 try 語句塊中的 return 語句以前執行。咱們再來看另外一個例子(清單 4)。
public class Test { public static void main(String[] args) { System.out.println("reture value of test() : " + test()); } public static int test(){ int i = 1; try { System.out.println("try block"); i = 1 / 0; return 1; }catch (Exception e){ System.out.println("exception block"); return 2; }finally { System.out.println("finally block"); } } }
清單 4 的執行結果爲:
try block exception block finally block reture value of test() : 2
清單 4 說明了 finally 語句塊在 catch 語句塊中的 return 語句以前執行。
從上面的清單 3 和清單 4,咱們能夠看出,其實 finally 語句塊是在 try 或者 catch 中的 return 語句以前執行的。更加通常的說法是,finally 語句塊應該是在控制轉移語句以前執行,控制轉移語句除了 return 外,還有 break 和 continue。另外,throw 語句也屬於控制轉移語句。雖然 return、throw、break 和 continue 都是控制轉移語句,可是它們之間是有區別的。其中 return 和 throw 把程序控制權轉交給它們的調用者(invoker),而 break 和 continue 的控制權是在當前方法內轉移。請你們先記住它們的區別,在後續的分析中咱們還會談到。
仍是得來點有說服力的證據,下面這段摘自 Java 語言規範第四版(《The Java™ Programming Language, Fourth Edition》),請讀者本身體會一下其含義。
好了,看到這裏,是否是有人認爲本身已經掌握了 finally 的用法了?先別忙着下結論,咱們再來看兩個例子 – 清單 5 和清單 6。
public class Test { public static void main(String[] args) { System.out.println("return value of getValue(): " + getValue()); } public static int getValue() { try { return 0; } finally { return 1; } } }
清單 5 的執行結果:
return value of getValue(): 1
public class Test { public static void main(String[] args) { System.out.println("return value of getValue(): " + getValue()); } public static int getValue() { int i = 1; try { return i; } finally { i++; } } }
清單 6 的執行結果:
return value of getValue(): 1
利用咱們上面分析得出的結論:finally 語句塊是在 try 或者 catch 中的 return 語句以前執行的。 由此,能夠輕鬆的理解清單 5 的執行結果是 1。由於 finally 中的 return 1;語句要在 try 中的 return 0;語句以前執行,那麼 finally 中的 return 1;語句執行後,把程序的控制權轉交給了它的調用者 main()函數,而且返回值爲 1。那爲何清單 6 的返回值不是 2,而是 1 呢?按照清單 5 的分析邏輯,finally 中的 i++;語句應該在 try 中的 return i;以前執行啊? i 的初始值爲 1,那麼執行 i++;以後爲 2,再執行 return i;那不就應該是 2 嗎?怎麼變成 1 了呢?
關於 Java 虛擬機是如何編譯 finally 語句塊的問題,有興趣的讀者能夠參考《 The JavaTM Virtual Machine Specification, Second Edition 》中 7.13 節 Compiling finally。那裏詳細介紹了 Java 虛擬機是如何編譯 finally 語句塊。實際上,Java 虛擬機會把 finally 語句塊做爲 subroutine(對於這個 subroutine 不知該如何翻譯爲好,乾脆就不翻譯了,省得產生歧義和誤解。)直接插入到 try 語句塊或者 catch 語句塊的控制轉移語句以前。可是,還有另一個不可忽視的因素,那就是在執行 subroutine(也就是 finally 語句塊)以前,try 或者 catch 語句塊會保留其返回值到本地變量表(Local Variable Table)中。待 subroutine 執行完畢以後,再恢復保留的返回值到操做數棧中,而後經過 return 或者 throw 語句將其返回給該方法的調用者(invoker)。請注意,前文中咱們曾經提到過 return、throw 和 break、continue 的區別,對於這條規則(保留返回值),只適用於 return 和 throw 語句,不適用於 break 和 continue 語句,由於它們根本就沒有返回值。
轉自:http://www.ibm.com/developerworks/cn/java/j-lo-finally/