final、finally、finalize

final關鍵字 
先看看final關鍵字,它能夠被用於如下幾個地方: 
一、修飾屬性、局部變量、方法參數:
若是final修飾的是一個基本類型,就表示這個變量所賦予的值不可修改,即它是個常量;若是final修飾的是一個對象,就表示這個變量被賦予的引用不可修改(但咱們能夠修改該引用所指向對象裏的內容,這裏所說的不可修改是指final修改的引用一但指向了誰,就不能再指向別的對象了)。下面來看看修改屬性與變量時須要注意的幾點:

在方法中定義的內部類只能訪問方法中的final類型的局部變量,由於用final定義的局部變量是一個常量,運行時不是放在棧裏的,所以它的生命同期超出了方法運行的生命週期:
編程

Java代碼  收藏代碼函數

  1. //final不能去掉,不然編譯通不過  spa

  2. public Comparable f(final Comparable o1) {  指針

  3.     return new Comparable() {  orm

  4.         public int compareTo(Object o2) {  對象

  5.             return o1.compareTo(o2);  blog

  6.         }  繼承

  7.     };  接口

  8. }  生命週期

final修改的靜態屬性必須在聲明的同時或者在靜態塊中初始化;final修飾的非靜態屬性,必須在聲明的同時、或非靜態塊中或者是構造函數中初始化:

Java代碼  收藏代碼

  1. public class A {  

  2.     private final int a = 1;//非靜態屬性在定義時初始化  

  3.     private final static int b = 1;//靜態屬性在定義時初始化  

  4.   

  5.     private final int c;//非靜態屬性在定義時未初始化  

  6.     {  

  7.         //非靜態屬性在非靜態塊中初始化  

  8.         c = 1;  (對)

  9.     }  

  10.   

  11.     private final static int d;//靜態屬性在定義時未初始化  

  12.     static {  

  13.         //靜態屬性在靜態塊中初始化  

  14.         d = 1;  (對)

  15.     }  

  16.   

  17.     private final int e;//非靜態屬性在定義時未初始化  

  18.   

  19.     A() {  

  20.         //非靜態屬性在構造函數中初始化  

  21.         e = 1;  (對)

  22.     }  

  23. }  

   靜態屬性不能在非靜態塊中初始化(由於非靜態塊是在new時才調用,而靜態屬性在對象尚未建立時也能使用(靜態屬性在類加載的時候進行了初始化));         

非靜態屬性不能在靜態塊中(由於在靜態塊中不能訪問非靜態屬性、變量及方法)初始化,能夠在非靜態塊或構造函數中初始化

Java代碼  收藏代碼

  1. public class A {  

  2.     private final int a;//!! 非靜態屬性未初始化  

  3.     private final static int b;//!! 靜態屬性未初始化  

  4.   

  5.     private final int c;  

  6.     static {  

  7.         //!! 非靜態屬性不能在靜態塊中初始化  

  8.         c = 1;  (錯)

  9.     }  

  10.   

  11.     private final static int d;  

  12.     {  

  13.         //!! 靜態屬性不能在非靜態塊中初始化  

  14.         d = 1;  (錯)

  15.     }  

  16.   

  17.     private final static int e;  

  18.   

  19.     A() {  

  20.         //!! 靜態屬性不能在構造函數中初始化  

  21.         e = 1;  (錯)

  22.     }  

  23. }  

接口中的屬性成員默認就是 public final static,只能在定義時就初始化:方法默認是public abstract

Java代碼  收藏代碼

  1. package A;  

  2.   

  3. public interface A {  

  4.     //接口中的屬性成員默認就是 public final static  

  5.     int i = 1;  

  6.   

  7.     // !! 接口中的訪問修飾符只能是 public  (Illegal modifier for the interface field idd.a; only public, static & final are permitted) ,但可不寫  

  8.     //protected int a = 1;  (錯)

  9.   

  10.     // !! 接口中的屬性只能在定義時就初始化  

  11.     //    public static final int b;  (錯)

  12.          public static final int b=0;  (對)

  13.   

  14.     // !! 接口中的屬性是常量,不能在靜態塊與非靜態塊中初始化,由於接口中不能有靜態塊與非靜態塊  

  15.     //   (錯) static{  

  16.     //        b=1;  

  17.     //    }  

  18.   

  19.     //   (錯) {  

  20.     //        b=1;  

  21.     //    }  

  22. //   接口中方法的訪問修飾符只能是 public  (Illegal modifier for the interface method ssss; only public & abstract are permitted) ,但可不寫   

  23.  //  public  void ssss();



  1. }  

  2.   

  3. package B;  

  4.   

  5. import A.A;  

  6.   

  7. public class B {  

  8.     public static void main(String[] args) {  

  9.         // !! 不能修改,由於接口中的定義的屬性默認就是final  

  10.         //A.i = 2;  (錯)

  11.   

  12.         //接口中的定義的屬性默認就是public final static,由於能夠被不一樣包靜態訪問  

  13.         System.out.println(A.i);  

  14.     }  

  15. }  

這裏提到了靜態區與非靜態區,它們的區別是,靜態區在類裝載時執行一次,而非靜態區每在實例化一個對象時就執行一次:

Java代碼  收藏代碼

  1. public class A {  

  2.     static {  

  3.         System.out.println("static block");  

  4.     }  

  5.   

  6.     {  

  7.         System.out.println("block");  

  8.     }  

  9.   

  10.     public static void main(String[] args) {  

  11.         new A();  

  12.         new A();  

  13.     }  

  14.     /* output: 

  15.     static block 

  16.     block 

  17.     block 

  18.      */  

  19. }  

另外,用final修飾的變量會有更高的效率,若是一個變量不在變化時,那麼它就應該定義成常量,因此在須要的地方咱們儘可能使用常量,由於這樣在編譯時期就能肯定。

二、修飾方法:
被final修改的方法不能被覆寫。

Java代碼  收藏代碼

  1. class A {  

  2.     public final void f() {}  

  3. }  

  4.   

  5. class B extends A {  

  6.     // !! 不能覆寫final方法  

  7.     //    public void f() {}  (錯)

  8.     //    public final void f() {}  (錯)

  9. }  

private方法默認就是final方法,編譯器在處理private方法時,是按照final方法來對待的,這樣能夠提升該方法被調用時的效率

三、修飾類
final類不容許被繼承(若是String類),編譯器在處理時把它的全部方法都看成final的(但數據成員既能夠是final,也能夠不是,以定義時前面修飾爲準),所以final類比普通類擁有更高的效率:

Java代碼  收藏代碼

  1. final class A {  

  2.     //注,final中的屬性能夠是final,也能夠不是,以定義時前面修飾爲準  

  3.     int i = 1;  

  4.   

  5.     public final void f() {}  

  6.   

  7.     //final類中的全部方法默認就是final方法  

  8.     void m() {}  

  9. }  

  10.   

  11. // !! final 類不能繼承  

  12. //class B extends A {}  

  13.   

  14. public class C {  

  15.     public static void main(String[] args) {  

  16.         A a = new A();  

  17.         a.i = 2;//能夠修改final類的非final屬性成員  

  18.     }  

  19. }  

接口與抽象類不能用final來修飾,即final interface、final abstract class是不容許的

Java代碼  收藏代碼

  1. // !! 接口不能用final來修飾  

  2. public final interface A {}  (錯)

  3.   

  4. // !! 抽象類不能用final來修飾  

  5. public final abstract class A {}  (錯)

 
finally關鍵字 
finally關鍵字用在try/catch語句最末,表示不論是否拋出異常,finally塊中的語句最終確定、必定會被執行,執行的順序爲 try塊 —> finally塊(不拋異常狀況下)或 try塊 —> catch塊(拋異常狀況下)—> finally塊 :

Java代碼  收藏代碼

  1. try {//不拋異常狀況下  

  2.     System.out.println("try");  

  3. }  

  4. catch (Exception e) {  

  5.     System.out.println("catch");  

  6. }  

  7. finally {  

  8.     System.out.println("finally");  

  9. }  

  10.  System.out.println("last");  

  11. /* output: 

  12. try 

  13. finally 

  14. last

  15.  */  

  16.   

  17. try {//拋異常狀況下  

  18.     System.out.println("try");  

  19.     throw new NullPointerException();  

  20. }  

  21. catch (NullPointerException e) {  

  22.     System.out.println("catch");  

  23.     throw e;//再次拋出  

  24. }  

  25. finally {  

  26.     //不論是try塊仍是catch塊裏拋異常,finally塊最後必定會執行  

  27.     System.out.println("finally");  

  28. }  

  29. //  System.out.println("finally");  (錯) 編譯不經過;由於有了catch裏有了throw e;//catch裏再次拋出異常後,不能在finally後面再寫了,若是沒有在catch裏再拋出異常就能夠  

  30. 結果:

  31. /* output: 

  32. try 

  33. catch 

  34. finally 

  35.  */  

下面看看try、catch、finally有return語句時,到底從哪裏返回:

Java代碼  收藏代碼

  1. class A {  

  2.     public static void main(String[] args) {  

  3.         System.out.println(A.f1());//3  

  4.         System.out.println(A.f2());//2  

  5.         try {  

  6.             System.out.println(A.f3());//方法異常結束  

  7.         }  

  8.         catch (Exception e) {  

  9.             e.printStackTrace();  

  10.         }  

  11.         System.out.println(A.f4());//1  

  12.         System.out.println(A.f5());//4  

  13.   

  14.         try {  

  15.             System.out.println(A.f6());//方法異常結束  

  16.         }  

  17.         catch (Exception e) {  

  18.             e.printStackTrace();  

  19.         }  

  20.     }  

  21.   

  22.     /* 

  23.      * 若是 finally 塊中有 return 語句,則忽略 try、catch 塊中的retrun , 

  24.      * 但 finally 中有return不是一種好的編程方式,這樣會引發編譯時警告 

  25.      */  

  26.     public static int f1() {  

  27.         System.out.println("--f1()--");  

  28.         try {  

  29.             System.out.println("f1 - 1");  

  30.             nullExcp();//拋空指針異常  

  31.             return 1;  

  32.         }  

  33.         catch (NullPointerException e) {  沒執行)

  34.             System.out.println("f1 - 2");  

  35.             return 2;  

  36.         }  

  37.         finally {  

  38.             System.out.println("f1 - 3");  

  39.             return 3;//從這裏返回  

  40.         }  

  41.         /* 

  42.          * !! 這裏不能有語句,由於方法在此前已從finally塊中返回,或者finally 塊中已拋 

  43.          * 異常後方法結束,但要注意的是,無論catch塊中是否拋異常,最會執行finally塊 

  44.          */  

  45.         // return 4;  

  46.     }  


  47.   

  48.     /* 

  49.      * 若是 finally 塊中沒有 return 語句,但 try、catch 塊中有時,若是try中不拋 

  50.      * 異常,則從try語句塊中正常返回,若是try中拋出異常,則從catch塊中正常返回或者 

  51.      * catch拋出異常時方法異常結束 

  52.      */  

  53.     public static int f2() {  

  54.         System.out.println("--f2()--");  

  55.         try {  

  56.             System.out.println("f1 - 1");  

  57.             nullExcp();//拋空指針異常  

  58.             return 1;  

  59.         }  

  60.         catch (NullPointerException e) {  

  61.             System.out.println("f1 - 2");  

  62.             return 2;//從這裏返回  

  63.         }  

  64.         finally {  

  65.             System.out.println("f1 - 3");  

  66.         }  

  67.         /* 

  68.          * !! 這裏也不能有其餘語句了,由於到此方法已經正常或異常結束了 

  69.          */  

  70.         // return 4;  

  71.     }  

  72.   

  73.     //try與catch塊都拋異常,最後方法在執行完finally塊後從catch塊中異常結束  

  74.     public static int f3() {  

  75.         System.out.println("--f3()--");  

  76.         try {  

  77.             System.out.println("f1 - 1");  

  78.             nullExcp();//拋空指針異常  

  79.             return 1;  

  80.         }  

  81.         catch (NullPointerException e) {  

  82.             System.out.println("f1 - 2");  

  83.             nullExcp();//拋空指針異常,從這裏方法異常結束  

  84.             return 2;  

  85.         }  

  86.         finally {  

  87.             System.out.println("f1 - 3");  

  88.         }  

  89.         /* 

  90.          * !! 這裏也不能有其餘語句了,由於到此方法已經正常或異常結束了 

  91.          */  

  92.         // return 4;  

  93.     }  

  94.   

  95.     //這是咱們一般寫法,只在try或最後返回結果:正常從try中返回  

  96.     public static int f4() {  

  97.         System.out.println("--f4()--");  

  98.         try {  

  99.             System.out.println("f1 - 1");  

  100.             return 1;//從這裏返回  

  101.         }  

  102.         catch (NullPointerException e) {  

  103.             System.out.println("f1 - 2");  

  104.         }  

  105.         finally {  

  106.             System.out.println("f1 - 3");  

  107.         }  

  108.         return 4;  

  109.     }  

  110.   

  111.     //這是咱們一般寫法,只在try或最後返回結果:異常後從最後返回  

  112.     public static int f5() {  

  113.         System.out.println("--f5()--");  

  114.         try {  

  115.             System.out.println("f1 - 1");  

  116.             nullExcp();//拋空指針異常  

  117.             return 1;  

  118.         }  

  119.         catch (NullPointerException e) {  

  120.             System.out.println("f1 - 2");  

  121.         }  

  122.         finally {  

  123.             System.out.println("f1 - 3");  

  124.         }  

  125.         return 4;//從這裏返回  

  126.     }  

  127.   

  128.     public static int f6() {  

  129.         System.out.println("--f6()--");  

  130.         try {  

  131.             System.out.println("f1 - 1");  

  132.             nullExcp();//拋空指針異常  

  133.             return 1;  

  134.         }  

  135.         catch (NullPointerException e) {  

  136.             System.out.println("f1 - 2");  

  137.             nullExcp();//拋空指針異常,從這裏方法異常結束  

  138.         }  

  139.         finally {  

  140.             System.out.println("f1 - 3");  

  141.         }  

  142.         return 4;  

  143.     }  

  144.   

  145.     private static void nullExcp() {  

  146.         throw new NullPointerException();  

  147.     }  

  148. }  

從上面例子能夠看出return語句是不會阻止finally塊執行的,那麼continue和break可否阻止?答案是不會的,與return同樣,finally語句塊是在循環被跳過(continue)和中斷(break)以前被執行的:

Java代碼  收藏代碼

  1. class A {  

  2.     public static void main(String[] args) {  

  3.         int i = 0;  

  4.         System.out.println("--continue--");  

  5.         while (i++ <= 1) {  

  6.             try {  

  7.                 System.out.println("i=" + i);  

  8.                 continue;  

  9.             }  

  10.             catch (Exception e) {  

  11.                 e.printStackTrace();  

  12.             }  

  13.             finally {  

  14.                 System.out.println("finally");  

  15.             }  

  16.         }  

  17.         System.out.println("--break--");  

  18.         while (i++ <= 3) {  

  19.             try {  

  20.                 System.out.println("i=" + i);  

  21.                 break;  

  22.             }  

  23.             catch (Exception e) {  

  24.                 e.printStackTrace();  

  25.             }  

  26.             finally {  

  27.                 System.out.println("finally2");  

  28.             }  

  29.         }  

  30.     }  

  31. }  

  32. 結果:

  33. --continue--

  34.       i=1

  35.     finally

  36.      i=2

  37.     finally

  38.    --break--

  39.      i=4

  40.     finally2


 

finalize關鍵字 
finalize()是Object類的一個方法,finalize()方法是GC(garbage collector)運行機制的一部分,由對象的垃圾回收器調用此方法,當一個對象被回收時,finalize()方法將會被調用。但咱們要注意的是,若是 finalize 方法拋出未捕獲的異常,那麼該異常將被忽略,而且該對象的終結操做將終止:

Java代碼  收藏代碼

  1. protected void finalize() throws Throwable {  

  2.     System.out.println("finalize");  

  3. }  

  4. public static void main(String[] args) {  

  5.     A a = new A();  

  6.     a = null;  

  7.     //加快GC回收,但不必定立刻執行加收動做,由虛擬機決定  

  8.     System.gc();  

  9. }



參考原文地址:http://jiangzhengjun.iteye.com/blog/577045

相關文章
相關標籤/搜索