首頁  >  文章  >  Java  >  匿名內部類精講

匿名內部類精講

高洛峰
高洛峰原創
2016-12-15 12:25:201189瀏覽

匿名內部類別適合建立那種只需要一次使用的類,例如命令模式時所需要的Command物件。匿名內部類別的語法有點奇怪,在創建匿名內部類別時會立即創建一個該類別的實例,這個類別定義立即消失,匿名內部類別不能重複使用。
定義匿名內部類別的格式如下:

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實作類別物件的程式碼,可以拆分成以下程式碼:

class AnonymousProduct implements Product{  
  public double getPrice(){  
   return 567;  
    }  
  public String getName(){  
   return "AGP显卡";  
    }  
 }  
 ta.test(new AnonymousProduct());

當透過實作介面來建立匿名內部類別時,匿名內部類別也不能顯示建立建構器,因此匿名內部類別只有一個隱式的無參數建構
器,故new介面名後的括號裡不能傳入參數值。
    但如果透過繼承父類別來建立匿名內部類別是,匿名內部類別將擁有和父類別相似的建構器,此處的相似指的是擁有相同的形參
列表。

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修飾符來修飾外部類別的局部變量,
否則系統將會錯誤。

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修飾符修飾,所以粗體字程式碼將
引起編譯異常。


更多匿名內部類精講相關文章請關注PHP中文網!


陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn