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

相关文章
相关标签/搜索