上面就是這樣一個例子。在方法dest中我們定義了一個內(nèi)部類,最后由這個方法返回這個內(nèi)部類的對象。如果我們在用一個內(nèi)部類的時候僅需要創(chuàng)建它的一個對象并創(chuàng)給外部,就可以這樣做。當(dāng)然,定義在方法中的內(nèi)部類可以使設(shè)計(jì)多樣化,用途絕不僅僅在這一點(diǎn)。
下面有一個更怪的例子:
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 之外創(chuàng)建這個內(nèi)部類的對象,因?yàn)檫@已經(jīng)超出了它的作用域。不過在編譯的時候,內(nèi)部類 TrackingSlip 和其他類一樣同時被編譯,只不過它由它自己的作用域,超出了這個范圍就無效,除此之外它和其他內(nèi)部類并沒有區(qū)別。
2.匿名類
匿名類是不能有名稱的類,所以沒辦法引用他們。必須在創(chuàng)建時,作為new語句的一部分來聲明他們。
這就要采用另一種形式的new語句,如下所示:
new <類或接口> <類的主體>
這種形式的new語句聲明一個新的匿名類,他對一個給定的類進(jìn)行擴(kuò)展,或?qū)崿F(xiàn)一個給定的接口。他還創(chuàng)建那個類的一個新實(shí)例,并把他作為語句的結(jié)果而返回。要擴(kuò)展的類和要實(shí)現(xiàn)的接口是new語句的操作數(shù),后跟匿名類的主體。
假如匿名類對另一個類進(jìn)行擴(kuò)展,他的主體能夠訪問類的成員、覆蓋他的方法等等,這和其他任何標(biāo)準(zhǔn)的類都是相同的。假如匿名類實(shí)現(xiàn)了一個接口,他的主體必須實(shí)現(xiàn)接口的方法。
注意匿名類的聲明是在編譯時進(jìn)行的,實(shí)例化在運(yùn)行時進(jìn)行。這意味著for循環(huán)中的一個new語句會創(chuàng)建相同匿名類的幾個實(shí)例,而不是創(chuàng)建幾個不同匿名類的一個實(shí)例。
從技術(shù)上說,匿名類可被視為非靜態(tài)的內(nèi)部類,所以他們具備和方法內(nèi)部聲明的非靜態(tài)內(nèi)部類相同的權(quán)限和限制。
假如要執(zhí)行的任務(wù)需要一個對象,但卻不值得創(chuàng)建全新的對象(原因可能是所需的類過于簡單,或是由于他只在一個方法內(nèi)部使用),匿名類就顯得很有用。匿名類尤其適合在Swing應(yīng)用程式中快速創(chuàng)建事件處理程式。
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 也可以是一個類,但是你外部調(diào)用的方法必須在你的這個類或接口中聲明,外部不能調(diào)用匿名類內(nèi)部的方法。
Java 中內(nèi)部匿名類用的最多的地方也許就是在 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); } } |
內(nèi)部匿名類,就是建立一個內(nèi)部的類,但沒有給你命名,也就是沒有引用實(shí)例的變量。
new WindowAdapter() { public void windowClosing(WindowEvent e) { dispose(); System.exit(0); } } |
new 是建立一個 WindowAdapter 對象,后面一個 {} 表示這個括號中的操作作用于這個默認(rèn)的對名象,而上面的 Java 程序中后面是一個函數(shù)體。
這個用法的作用是:創(chuàng)建一個對象的實(shí)例,并且 override 它的一個函數(shù)。
打開 WindowAdapter 的代碼可以發(fā)現(xiàn)。它是一個抽象類。它是對 WindowListener 接口的一個實(shí)現(xiàn)。
Frame.addWindowListner(); 的參數(shù)是一個 WindowListner ,而實(shí)現(xiàn)上是傳一個從WindowAdapter 派生出的一個匿名類。
有一點(diǎn)需要注意的是,匿名內(nèi)部類由于沒有名字,所以它沒有構(gòu)造函數(shù)(但是如果這個匿名內(nèi)部類繼承了一個只含有帶參數(shù)構(gòu)造函數(shù)的父類,創(chuàng)建它的時候必須帶上這些參數(shù),并在實(shí)現(xiàn)的過程中使用 super 關(guān)鍵字調(diào)用相應(yīng)的內(nèi)容)。如果你想要初始化它的成員變量,有下面幾種方法:
1. 如果是在一個方法的匿名內(nèi)部類,可以利用這個方法傳進(jìn)你想要的參數(shù),不過記住,這些參數(shù)必須被聲明為 final 。
2. 將匿名內(nèi)部類改造成有名字的局部內(nèi)部類,這樣它就可以擁有構(gòu)造函數(shù)了。
3. 在這個匿名內(nèi)部類中使用初始化代碼塊。