上面就是這樣一個例子。在方法dest中我們定義了一個內部類,最后由這個方法返回這個內部類的對象。如果我們在用一個內部類的時候僅需要創建它的一個對象并創給外部,就可以這樣做。當然,定義在方法中的內部類可以使設計多樣化,用途絕不僅僅在這一點。
下面有一個更怪的例子:
public class Goods2{ private void internalTracking(boolean b) { if(b) { class TrackingSlip { private String id; TrackingSlip(String s) { id = s; } String getSlip() { return id; } } TrackingSlip ts = new TrackingSlip("slip"); String s = ts.getSlip(); } } public void track() { internalTracking(true); } public static void main(String[] args) { Goods2 g= new Goods2(); g.track(); } } |
你不能在 if 之外創建這個內部類的對象,因為這已經超出了它的作用域。不過在編譯的時候,內部類 TrackingSlip 和其他類一樣同時被編譯,只不過它由它自己的作用域,超出了這個范圍就無效,除此之外它和其他內部類并沒有區別。
2.匿名類
匿名類是不能有名稱的類,所以沒辦法引用他們。必須在創建時,作為new語句的一部分來聲明他們。
這就要采用另一種形式的new語句,如下所示:
new <類或接口> <類的主體>
這種形式的new語句聲明一個新的匿名類,他對一個給定的類進行擴展,或實現一個給定的接口。他還創建那個類的一個新實例,并把他作為語句的結果而返回。要擴展的類和要實現的接口是new語句的操作數,后跟匿名類的主體。
假如匿名類對另一個類進行擴展,他的主體能夠訪問類的成員、覆蓋他的方法等等,這和其他任何標準的類都是相同的。假如匿名類實現了一個接口,他的主體必須實現接口的方法。
注意匿名類的聲明是在編譯時進行的,實例化在運行時進行。這意味著for循環中的一個new語句會創建相同匿名類的幾個實例,而不是創建幾個不同匿名類的一個實例。
從技術上說,匿名類可被視為非靜態的內部類,所以他們具備和方法內部聲明的非靜態內部類相同的權限和限制。
假如要執行的任務需要一個對象,但卻不值得創建全新的對象(原因可能是所需的類過于簡單,或是由于他只在一個方法內部使用),匿名類就顯得很有用。匿名類尤其適合在Swing應用程式中快速創建事件處理程式。
interface pr { void print1(); } public class noNameClass { public pr dest() { return new pr() { public void print1() { System.out.println("Hello world!!"); } }; } } public static void main(String args[]) { noNameClass c = new noNameClass(); pr hw = c.dest(); hw.print1(); } |
pr 也可以是一個類,但是你外部調用的方法必須在你的這個類或接口中聲明,外部不能調用匿名類內部的方法。
Java 中內部匿名類用的最多的地方也許就是在 Frame 中加入 Listner 了吧。
import java.awt.*; import java.awt.event.*; public class QFrame extends Frame { public QFrame() { this.setTitle(\"my application\"); addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { dispose(); System.exit(0); } }); this.setBounds(10,10,200,200); } } |
內部匿名類,就是建立一個內部的類,但沒有給你命名,也就是沒有引用實例的變量。
new WindowAdapter() { public void windowClosing(WindowEvent e) { dispose(); System.exit(0); } } |
new 是建立一個 WindowAdapter 對象,后面一個 {} 表示這個括號中的操作作用于這個默認的對名象,而上面的 Java 程序中后面是一個函數體。
這個用法的作用是:創建一個對象的實例,并且 override 它的一個函數。
打開 WindowAdapter 的代碼可以發現。它是一個抽象類。它是對 WindowListener 接口的一個實現。
Frame.addWindowListner(); 的參數是一個 WindowListner ,而實現上是傳一個從WindowAdapter 派生出的一個匿名類。
有一點需要注意的是,匿名內部類由于沒有名字,所以它沒有構造函數(但是如果這個匿名內部類繼承了一個只含有帶參數構造函數的父類,創建它的時候必須帶上這些參數,并在實現的過程中使用 super 關鍵字調用相應的內容)。如果你想要初始化它的成員變量,有下面幾種方法:
1. 如果是在一個方法的匿名內部類,可以利用這個方法傳進你想要的參數,不過記住,這些參數必須被聲明為 final 。
2. 將匿名內部類改造成有名字的局部內部類,這樣它就可以擁有構造函數了。
3. 在這個匿名內部類中使用初始化代碼塊。