來看一個例子:html
class A{ public B f() { return new B() { { setName("annoyInner"); //非靜態初始塊,等同於構造方法 } //。。。 //能夠自定義成員變量、成員方法 //能夠重寫父類方法 }; } public static void main(String[] args) { A a = new A(); System.out.println(a.f().getName()); } } class B{ private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } public B() { System.out.println("B的無參構造"); } }
打印結果:性能
B的無參構造
annoyInner
在匿名類中,可用花括號括起來進行一些必要的初始化操做,表示非靜態初始化塊,等同於構造方法。因爲沒有方法名,此構造方法不區分有參無參,那麼怎麼在匿名構造方法中使用參數呢?學習
class A{ public B f() { String name = "annoyInner"; return new B() { { setName(name); //直接使用局部變量便可 } //。。。 //能夠自定義成員變量、成員方法 //能夠重寫父類方法 }; } public static void main(String[] args) { A a = new A(); System.out.println(a.f().getName()); } } class B{ private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } public B() { System.out.println("B的無參構造"); } }
打印結果同上。匿名類中直接使用局部變量或成員變量便可,至關於匿名類的有參構造器(Java 中局部內部類和匿名內部類訪問的局部變量必須由 final 修飾,以保證內部類和外部類的數據一致性。但從 Java 8 開始,添加了 Effectively final 功能,咱們能夠不加 final 修飾符,由系統默認添加。詳情可點擊《Java8新特性之Effectively final》進行學習。)優化
接下來又有個問題,匿名類的構造器能不能重載呢?this
答案是不能,仍是由於匿名類沒有名字,連賦予參數的地方都沒有,可是你能夠這樣寫:spa
class A{ public B f() { return new B() { { setName("annoyInner1"); } { setName("annoyInner2"); } { setName("annoyInner3"); } //... }; } public static void main(String[] args) { A a = new A(); System.out.println(a.f().getName()); } }
打印結果是annoyInner3,這至關因而多個初始化塊,會依次執行,並非構造器的重載,可是這樣寫跟寫在一個初始化塊中沒有什麼區別。.net
咱們都知道匿名類實例化時會默認調用父類的無參構造,如何調用父類的有參構造?加上super(name)是不行的:code
class A{ public B f() { return new B("annoyInner") { { //super(name); //編譯報錯 } }; } public static void main(String[] args) { A a = new A(); System.out.println(a.f().getName()); } } class B{ private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } public B() { System.out.println("B的無參構造"); } public B(String name) { this.name = name; System.out.println("B的有參構造"); } }
打印結果以下,直接在匿名類的表達式中使用父類的有參構造便可htm
B的有參構造
annoyInner
下面是一個很常見的匿名類的運用,常常看見有人這麼寫:blog
ArrayList<String> list = new ArrayList<String>() {{ add("A"); add("B"); add("C"); }}; Map m = new HashMap() { { put("name","zhangsan"); put("age",18); } };
看到這個,我只想說:
花裏胡哨!!!
拿arrayList爲例,外層的花括號建立了一個繼承於ArrayList的匿名類,裏層的花括號表示在這個匿名類的初始化塊中調用了繼承而來的add方法,實際上這個匿名類和ArrayList沒有什麼區別。這樣寫好像是簡潔了一些,可是可讀性也要差一些,也並不會帶來多少性能上的優化,目前本人還不知道會不會引起什麼問題。不過取決於我的喜愛,用用也無妨。