Java:雙括號初始化 /匿名內部類初始化法

偶然見到一種初始化方式,感到十分新奇:java

//新建一個列表並賦初值A、B、C ArrayList<String> list = new ArrayList<String>() {{ add("A"); add("B"); add("C"); }};

還有其餘集合好比HashMap的初始化:數組

Map map = new HashMap() {{   put("Name", "Unmi");   put("QQ", "1125535"); }};

這種方式比起先new出對象,再一條條add,顯得更加簡潔和優雅。一開始沒想通什麼原理,後來查了一下才知道這種方法被稱爲雙大括號初始化(double brace initialization)或者匿名內部類初始化法,其實是一種取巧的方式。app

理解:

這裏以ArrayList的例子解釋,首先第一層花括號定義了一個繼承於ArrayList的匿名內部類 (Anonymous Inner Class)測試

//定義了一個繼承於ArrayList的類,它沒有名字 new ArrayList<String>(){ //在這裏對這個類進行具體定義 };

第二層花括號其實是這個匿名內部類實例初始化塊 (Instance Initializer Block)(或稱爲非靜態初始化塊):this

new ArrayList<String>(){ { //這裏是實例初始化塊,能夠直接調用父類的非私有方法或訪問非私有成員 } };

咱們經過new獲得這個ArrayList的子類的實例並向上轉型爲ArrayList的引用:spa

ArrayList<String> list = new ArrayList<String>() {{}};
  • 咱們獲得的其實是一個ArrayList的子類的引用,雖然這個子類相比ArrayList並無任何功能上的改變。
  • 能夠認爲這是個自己裝有數據的子類(由於它的數據來自於自身的初始化),而不是取得引用後再賦值。

下面自定義一個類並使用這種方式初始化:code

class Person{ protected String name; protected int age; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } } ... public static void main(String[] args) { Person p = new Person(){ { name = "xiaoming"; //或者調用setName() age = 3; //或者setAge() } }; System.out.println(p.getName() + p.getAge()); }

注意:

(1)這種方法必定程度上使代碼更簡潔,但同時可能下降可讀性;還可能會形成內存泄露,在序列化時可能也會出現一些問題(未測試)。

(2)當咱們想構造一個數組列表,並將它傳遞到一個方法時,最初的寫法以下:對象

ArrayList<String>  friends=new ArrayList<>();繼承

friends.add("tom");ip

friends.add("lin");

invite(friends);

若是不想要寫這個數組列表,可將其做爲一個匿名列表,經過雙括號的方式爲列表添加元素,這樣代碼更爲簡潔。

invite(new ArrayList<String> ()

{

     {

             add("tom");

             add("lin");

            }

})

外層「{}」建立了ArrayLIst的一個匿名子類,內層「{}」建立了一個對象構造塊。

相關文章
相關標籤/搜索