在Java中通過final關鍵字來聲明對象具有不變性(immutable),這裡的對象包括變量,方法,類,與C++中的const關鍵字效果類似。
immutable指對像在創建之後,狀態無法被改變可以從三個角度考慮使用final關鍵字:
final 變量
定義final Object a,則a只能被初始化一次,一旦初始化,a的數據無法修改,若a為引用類型,則不能重新綁定其他對象。
未被初始化的final變量被稱為blank final,若為成員變量,則必須被初始化或在構造器中賦值。
例子:
class Circle { static final double PI = 3.1415926; final int radius = 5; final int xPos; final int yPos; public Circle(int x, int y) { xPos = x; yPos = y; }} final 方法
定義final method,則該方法無法被重載,方法設計者不希望由於對方法的重載導致其他相關功能出現異常。
例子:
class BaseClass { public final void method() {}}class DerivedClass extends BaseClass { public final void method() {} // 編譯出錯}需要注意的是,final方法的定義不一定能夠產生inline的效果,因為方法是否inline取決於JVM的策略,而非final關鍵字,通過final的設計提高方法效率是不准確的。
final 類
final class X定義的類X無法被繼承。
在Java中,String類被設計成final,其定義如下
複製代碼代碼如下:
public class final String extends Object implements Serializable, Comparable<String>, CharSequence
內部類與final
在一個方法內定義匿名內部類時,內部類只能訪問方法內的final類型變量,使得Java編譯器能夠提前捕獲變量的值,並在內部類保存一份副本,當方法銷毀時,內部類的內存空間依然完整。
例子:
public class Wrapper { public static void main(String[] args) { // Object obj = null; //編譯出錯final Object obj = null; new Thread(new Runnable() { public void run() { obj = "hello"; } }).start(); }} PS:內部匿名類無法訪問外面的非final 的變量的問題
這個聽起來有點拗口,其實我更多的是想說Java 內部類的一些特性。
之所以會想起這個題目只要是最近在閱讀JDK 源碼中關於HTTP keepalive 的代碼時,其中一個源文件sun.net.www.protocol.http.HttpURLConnection.java 無意中看到下面這段代碼。
final boolean result[] = {false};java.security.AccessController.doPrivileged(new java.security.PrivilegedAction() { public Object run() { try { InetAddress a1 = InetAddress.getByName(h1); InetAddress a2 = InetAddress.getByName(h2); result[0] = a1.equals(a2); } catch (UnknownHostException e) { } catch (SecurityException e) { } return null; }});return result[0];Java 的匿名內部類無法訪問對應的函數的非final 變量。要想訪問外部的local variable, 這個variable 又必須要先定義成fianl, 但是一定義成final 就不能在匿名內部類中修改這個變量的值,所以要想匿名內部類返回一些有用的值時不是那麼的容易。這段代碼使用了一個非常巧妙的方法,這裡使用數組的方式繞過這個限制,雖然我們無法修改result 這個變量的引用,但是我們可以修改result 指向的那個數組的內容。
只是想記錄一下內部匿名類修改外部變量的一個小技巧。不過既然已經到了這裡,不妨繼續的看看內部類都有哪些特性或者限制吧。
在繼續本文前,我覺得非常有必要的明確下本文中涉及的一些Java 術語,這些術語不太好翻譯成中文,所以我們還是用英文來描述。
// This is classpublic class JavaTerm { // field or member variable private int field; // constructor public JavaTerm() { } // method public void method() { // local variable int localVariable = 0; // local class class LocalClass { public LocalClass() { } } // anonymous class new Runnable() { public void run() { } }; }}我們今天更多的將關注於local class 和anonymous class,它們都屬於inner class。
Java 允許我們在一個class 裡面再定義一個class, 稱為嵌套類(nested class), nested class 又可以分為兩類,一類是static nested class, 另外一個是non-static nested class, 又稱為inner class。 inner class 又可以分為local class 和anonymous class。
anonymous class 的一些限制