匿名內部類適合建立那種只須要一次使用的類,例如命令模式時所須要的Command對象。匿名內部類的語法有點奇怪,建立匿名內部類時會當即建立一個該類的實例,這個類定義當即消失,匿名內部類不能重複使用。
定義匿名內部類的格式以下:this
源碼打印?.net
- new 父類構造器(參數列表)|實現接口()
- {
- //匿名內部類的類體部分
- }
從上面定義能夠看出,匿名內部類必須繼承一個父類,或實現一個接口,但最多隻能繼承一個父類,或實現一個接口。
關於匿名內部類還有以下兩條規則:
1)匿名內部類不能是抽象類,由於系統在建立匿名內部類的時候,會當即建立內部類的對象。所以不容許將匿名內部類
定義成抽象類。
2)匿名內部類不等定義構造器,由於匿名內部類沒有類名,因此沒法定義構造器,但匿名內部類能夠定義實例初始化塊,
經過實例初始化塊來完成構造器須要完成的事情。
最經常使用的建立匿名內部類的方式是須要建立某個接口類型的對象,以下程序所示:對象
源碼打印?繼承
- interface Product{
- public double getPrice();
- public String getName();
- }
- public class TestAnonymous{
- public void test(Product p){
- System.out.println("購買了一個"+p.getName()+",花掉 了"+p.getPrice());
- }
- public static void main(String[]args){
- TestAnonymous ta = new TestAnonymous();
- ta.test(new Product(){
- public double getPrice(){
- return 567;
- }
- public String getName(){
- return "AGP顯卡";
- }
- });
- }
- }
上面程序中的TestAnonymous類定義了一個test方法,該方法須要一個Product對象做爲參數,但Product只是一個接口,
沒法直接建立對象,所以此處考慮建立一個Product接口實現類的對象傳入該方法---若是這個Product接口實現類須要重複
使用,則應該經該實現類定義一個獨立類;若是這個Product接口實現類只需一次使用,則可採用上面程序中的方式,定義
一個匿名內部類。
正如上面程序中看到,定義匿名類不須要class關鍵字,而是在定義匿名內部類時直接生成該匿名內部類的對象。上面
粗體字代碼部分就是匿名類的類體部分。
因爲匿名內部類不能是抽象類,因此匿名內部類必須實現它的抽象父類或者接口裏包含的全部抽象方法。
對於上面建立Product實現類對象的代碼,能夠拆分紅以下代碼:接口
源碼打印?get
- class AnonymousProduct implements Product{
- public double getPrice(){
- return 567;
- }
- public String getName(){
- return "AGP顯卡";
- }
- }
- ta.test(new AnonymousProduct());
當經過實現接口來建立匿名內部類時,匿名內部類也不能顯示建立構造器,所以匿名內部類只有一個隱式的無參數構造
器,故new接口名後的括號裏不能傳入參數值。
但若是經過繼承父類來建立匿名內部類是,匿名內部類將擁有和父類類似的構造器,此處的類似指的是擁有相同的形參
列表。源碼
源碼打印?io
- abstract class Device{
- private String name;
- public Device(){
- }
- public Device(String name){
- this.name = name;
- }
- public abstract double getPrice();
- //此處省略了name屬性的setter和getter方法
- }
- public class AnonymousInner{
- public void test(Device d){
- System.out.println("購買了一個"+d.getName()+",花掉了"+d.getPrice());
- }
- public static void main(String[] args){
- AnonymousInner ai = new AnonymousInner();
- //調用有參數的構造器建立Device匿名實現類的對象
- ai.test(new Device("電子示波器"){
- public double getPrice(){
- return 67;
- }
- });
- //調用無參數的構造器建立Device匿名實現類的對象
- Device d = new Device(){
- //初始化塊
- {
- System.out.println("匿名內部類的初始化塊...");
- }
- //實現抽象方法
- public double getPrice(){
- return 56;
- }
- public Sting getName(){
- return "鍵盤";
- }
- };
- ai.test(d);
- }
- }
上面程序建立了一個抽象父類Device,這個抽象父類裏包含兩個構造器:一個無參數的,一個有參數的。當建立以Device
爲父類的匿名內部類時,便可以傳入參數(如上面程序中第一段粗體字部分),也能夠不傳入參數(如上面程序中第二段粗體
字部分)。
當建立匿名內部類時,必須實現接口或抽象父類裏的全部抽象方法。若是有須要,也能夠重寫父類中的普通方法,如上面
程序的第二段粗體字代碼部分,匿名內部類重寫了抽象父類Device類的getName方法,其中getName方法並非抽象方法。
若是匿名內部類須要訪問外部類的局部變量,則必須使用final修飾符來修飾外部類的局部變量,
不然系統將報錯。編譯
源碼打印?class
- interface A{
- void test();
- }
- public class TestA{
- public static void main(Strign[] args){
- int age = 0;
- A a = new A(){
- public void test(){
- //下面語句將提示錯誤:匿名內部類內訪問局部變量必須使用final修飾
- System.out.println(age);
- }
- };
- }
- }
上面程序中粗體子代碼是匿名內部類訪問了外部類的局部變量,因爲age變量沒有使用final修飾符修飾,因此粗體字代碼將 引發編譯異常。