匿名內部類詳解


匿名內部類

匿名內部類就是沒有名字的內部類;


注意:

匿名內部類不能定義任何靜態成員、方法。

匿名內部類中的方法不能是抽象的;

匿名內部類必須實現接口或抽象父類的所有抽象方法。

匿名內部類訪問的外部類成員變量或成員方法必須用static修飾;


代碼:

接口

public interface Inner {
    public String say();
}

抽象類

public abstract class Inner1 implements Inner {
}

普通類

public class Inner2 implements Inner {
    public String say() {
        return "this is Inner2";
    }
}

外部類

public class Outer {

    public static String s1 = "this is s1 in Outer";
    public static String s2 = "this is s2 in Outer";
    private static String s3 = "this is s3 in Outer";

    public void method1(Inner inner) {
        System.out.println(inner.say());
    }

    private static String method2() {
        return "this is method2 in Outer";
    }

    public static void main(String[] args) {
        Outer outer = new Outer();
        // 測試1,Inner為接口
        outer.method1(new Inner() {
            String s1 = "this is s1 in Inner";

            public String say() {
                // 外部類和匿名函數類中有同名變量s1
                return s1;
            }
        });
        // 測試2,Inner1為抽象類
        outer.method1(new Inner1() {
            String s2 = "this is s2 in Inner1";

            public String say() {
                // 外部類和匿名函數類中有同名變量s2
                return Outer.s2;
            }
        });
        // 測試3,Inner2為普通類
        outer.method1(new Inner2() {
            public String say() {
                // 訪問外部類私有變量s3
                return s3;
            }
        });
        // 測試4,Inner2為普通類
        outer.method1(new Inner2() {
            public String say() {
                // 訪問外部類私有方法method1()
                return method2();
            }
        });
    }
}

打印:

this is s1 in Inner
this is s2 in Outer
this is s3 in Outer
this is method2 in Outer

分析:

編譯后自動生成四個文件:Outer$1.class、Outer$2.class、Outer$3.class、Outer$4.class。

Outer.class反編譯(屬性值、方法內容略)

public class jichu.Outer {
  public static java.lang.String s1;
  public static java.lang.String s2;
  private static java.lang.String s3;
  static {};
  public jichu.Outer();
  public void method1(jichu.Inner);
  private static java.lang.String method2();
  public static void main(java.lang.String[]);
  static java.lang.String access$0();
  static java.lang.String access$1();
}

Outer$1.class反編譯(經優化、調整)

class Outer$1
  implements Inner
{
  String s1 = "this is s1 in Inner";
  
  public String say()
  {
    return this.s1;
  }
}

Outer$2.class反編譯(經優化、調整)

class Outer$2
  extends Inner1
{
  String s2 = "this is s2 in Inner1";
  
  public String say()
  {
    return Outer.s2;
  }
}

Outer$3.class反編譯(經優化、調整)

class Outer$3
  extends Inner2
{
  public String say()
  {
    return Outer.access$0();
  }
}

Outer$4.class反編譯(經優化、調整)

class Outer$4
  extends Inner2
{
  public String say()
  {
    return Outer.access$1();
  }
}

1、匿名內部類因為沒有類名,可知匿名內部類不能定義構造器

2、因為在創建匿名內部類的時候,會立即創建它的實例,可知匿名內部類不能是抽象類,必須實現接口或抽象父類的所有抽象方法

3、匿名內部類會繼承一個父類(有且只有一個)或實現一個接口(有且只有一個),實現父類或接口中所有抽象方法,可以改寫父類中的方法,添加自定義方法。

5、當匿名內部類和外部類有同名變量(方法)時,默認訪問的是匿名內部類的變量(方法),要訪問外部類的變量(方法)則需要加上外部類的類名。

6、從Outer.class反編譯代碼中可看出自動生成了兩個靜態方法:access$0()和access$1(),並在測試3和測試4中通過Outer類名直接調用,這樣實現了內部類對外部類私有成員變量和方法的訪問。可知內部類可以訪問外部類私有變量和方法


疑問

匿名內部類不能含有static的變量和方法。但是測試發現變量可以被static final修飾,為什么?

主要是因為final類型在編譯期間jvm有優化,常量池會維護這些變量。雖然非靜態內部類不能脫離外部類這個上下文實例化,但是常量池使得final變量脫離了類實例化這個條件,編譯期間便可確定。


總結

1、匿名內部類不能定義任何靜態成員、方法。

2、匿名內部類中的方法不能是抽象的;

3、匿名內部類必須實現接口或抽象父類的所有抽象方法。

4、匿名內部類不能定義構造器;

5、匿名內部類訪問的外部類成員變量或成員方法必須用static修飾;

6、內部類可以訪問外部類私有變量和方法。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM