天天看點

匿名内部類精講

匿名内部類适合建立那種隻需要一次使用的類,例如指令模式時所需要的Command對象。匿名内部類的文法有點奇怪,建立匿名内部類時會立即建立一個該類的執行個體,這個類定義立即消失,匿名内部類不能重複使用。

    定義匿名内部類的格式如下:

[java] 

​​view plain​​​

​​​copy​​

  1. new 父類構造器(參數清單)|實作接口()
  2. {
  3. //匿名内部類的類體部分
  4. }

從上面定義可以看出,匿名内部類必須繼承一個父類,或實作一個接口,但最多隻能繼承一個父類,或實作一個接口。

 關于匿名内部類還有如下兩條規則:

 1)匿名内部類不能是抽象類,因為系統在建立匿名内部類的時候,會立即建立内部類的對象。是以不允許将匿名内部類

 定義成抽象類。

 2)匿名内部類不等定義構造器,因為匿名内部類沒有類名,是以無法定義構造器,但匿名内部類可以定義執行個體初始化塊,

 通過執行個體初始化塊來完成構造器需要完成的事情。

 最常用的建立匿名内部類的方式是需要建立某個接口類型的對象,如下程式所示:

[java] 

​​view plain​​​

​​​copy​​

  1. interface Product{
  2. public double getPrice();
  3. public String getName();
  4. }
  5. public class TestAnonymous{
  6. public void test(Product p){
  7. "購買了一個"+p.getName()+",花掉了"+p.getPrice());
  8. }
  9. public static void main(String[]args){
  10. TestAnonymous ta = new TestAnonymous();
  11. new Product(){  
  12. public double getPrice(){  
  13. return 567;  
  14.         }  
  15. public String getName(){  
  16. return "AGP顯示卡";  
  17.        }  
  18.    });  
  19. }
  20. }

上面程式中的TestAnonymous類定義了一個test方法,該方法需要一個Product對象作為參數,但Product隻是一個接口,

無法直接建立對象,是以此處考慮建立一個Product接口實作類的對象傳入該方法---如果這個Product接口實作類需要重複

使用,則應該經該實作類定義一個獨立類;如果這個Product接口實作類隻需一次使用,則可采用上面程式中的方式,定義

一個匿名内部類。

    正如上面程式中看到,定義匿名類不需要class關鍵字,而是在定義匿名内部類時直接生成該匿名内部類的對象。上面

粗體字代碼部分就是匿名類的類體部分。

 由于匿名内部類不能是抽象類,是以匿名内部類必須實作它的抽象父類或者接口裡包含的所有抽象方法。

 對于上面建立Product實作類對象的代碼,可以拆分成如下代碼:

[java] 

​​view plain​​​

​​​copy​​

  1. class AnonymousProduct implements Product{
  2. public double getPrice(){
  3. return 567;
  4. }
  5. public String getName(){
  6. return "AGP顯示卡";
  7. }
  8. }
  9. new AnonymousProduct());

 當通過實作接口來建立匿名内部類時,匿名内部類也不能顯示建立構造器,是以匿名内部類隻有一個隐式的無參數構造

器,故new接口名後的括号裡不能傳入參數值。

    但如果通過繼承父類來建立匿名内部類是,匿名内部類将擁有和父類相似的構造器,此處的相似指的是擁有相同的形參

清單。

[c-sharp] 

​​view plain​​​

​​​copy​​

  1. abstract class Device{
  2. private String name;
  3. public Device(){
  4. }
  5. public Device(String name){
  6. this.name = name;
  7. }
  8. public abstract double getPrice();
  9. //此處省略了name屬性的setter和getter方法
  10. }
  11. public class AnonymousInner{
  12. public void test(Device d){
  13. out.println("購買了一個"+d.getName()+",花掉了"+d.getPrice());
  14. }
  15. public static void main(String[] args){
  16. new AnonymousInner();
  17. //調用有參數的構造器建立Device匿名實作類的對象
  18. new Device("電子示波器"){
  19. public double getPrice(){
  20. return 67;
  21. }
  22. });
  23. //調用無參數的構造器建立Device匿名實作類的對象
  24. new Device(){
  25. //初始化塊
  26. {
  27. out.println("匿名内部類的初始化塊...");
  28. }
  29. //實作抽象方法
  30. public double getPrice(){
  31. return 56;
  32. }
  33. public Sting getName(){
  34. return "鍵盤";
  35. }
  36. };
  37. ai.test(d);
  38. }
  39. }

上面程式建立了一個抽象父類Device,這個抽象父類裡包含兩個構造器:一個無參數的,一個有參數的。當建立以Device

為父類的匿名内部類時,即可以傳入參數(如上面程式中第一段粗體字部分),也可以不傳入參數(如上面程式中第二段粗體

字部分)。

 當建立匿名内部類時,必須實作接口或抽象父類裡的所有抽象方法。如果有需要,也可以重寫父類中的普通方法,如上面

程式的第二段粗體字代碼部分,匿名内部類重寫了抽象父類Device類的getName方法,其中getName方法并不是抽象方法。

    如果匿名内部類需要通路外部類的局部變量,則必須使用final修飾符來修飾外部類的局部變量,

否則系統将報錯。

[java] 

​​view plain​​​

​​​copy​​

  1. interface A{
  2. void test();
  3. }
  4. public class TestA{
  5. public static void main(Strign[] args){
  6. int age = 0;
  7. new A(){
  8. public void test(){
  9. //下面語句将提示錯誤:匿名内部類内通路局部變量必須使用final修飾
  10. System.out.println(age);
  11. }
  12. };
  13. }
  14. }