java里匿名如何初始化_Java:雙括號初始化 /匿名內部類初始化法

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

//新建一個列表並賦初值A、B、C

ArrayList list = new ArrayList() {{

add("A");

add("B");

add("C");

}};

ZGF0YTppbWFnZS9naWY7YmFzZTY0LFIwbEdPRGxoQVFBQkFQQUJBUC8vL3dBQUFDSDVCQUVLQUFBQUxBQUFBQUFCQUFFQUFBSUNSQUVBT3c9PQ==ZGF0YTppbWFnZS9naWY7YmFzZTY0LFIwbEdPRGxoQVFBQkFQQUJBUC8vL3dBQUFDSDVCQUVLQUFBQUxBQUFBQUFCQUFFQUFBSUNSQUVBT3c9PQ==

還有其他集合比如HashMap的初始化:

Map map = new HashMap() {{

put("Name", "Unmi");

put("QQ", "1125535");

}};

ZGF0YTppbWFnZS9naWY7YmFzZTY0LFIwbEdPRGxoQVFBQkFQQUJBUC8vL3dBQUFDSDVCQUVLQUFBQUxBQUFBQUFCQUFFQUFBSUNSQUVBT3c9PQ==ZGF0YTppbWFnZS9naWY7YmFzZTY0LFIwbEdPRGxoQVFBQkFQQUJBUC8vL3dBQUFDSDVCQUVLQUFBQUxBQUFBQUFCQUFFQUFBSUNSQUVBT3c9PQ==

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

理解:

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

//定義了一個繼承於ArrayList的類,它沒有名字

new ArrayList(){

//在這里對這個類進行具體定義

};

ZGF0YTppbWFnZS9naWY7YmFzZTY0LFIwbEdPRGxoQVFBQkFQQUJBUC8vL3dBQUFDSDVCQUVLQUFBQUxBQUFBQUFCQUFFQUFBSUNSQUVBT3c9PQ==ZGF0YTppbWFnZS9naWY7YmFzZTY0LFIwbEdPRGxoQVFBQkFQQUJBUC8vL3dBQUFDSDVCQUVLQUFBQUxBQUFBQUFCQUFFQUFBSUNSQUVBT3c9PQ==

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

new ArrayList(){

{

//這里是實例初始化塊,可以直接調用父類的非私有方法或訪問非私有成員

}

};

ZGF0YTppbWFnZS9naWY7YmFzZTY0LFIwbEdPRGxoQVFBQkFQQUJBUC8vL3dBQUFDSDVCQUVLQUFBQUxBQUFBQUFCQUFFQUFBSUNSQUVBT3c9PQ==ZGF0YTppbWFnZS9naWY7YmFzZTY0LFIwbEdPRGxoQVFBQkFQQUJBUC8vL3dBQUFDSDVCQUVLQUFBQUxBQUFBQUFCQUFFQUFBSUNSQUVBT3c9PQ==

我們通過new得到這個ArrayList的子類的實例並向上轉型為ArrayList的引用:

ArrayList list = new ArrayList() {{}};

ZGF0YTppbWFnZS9naWY7YmFzZTY0LFIwbEdPRGxoQVFBQkFQQUJBUC8vL3dBQUFDSDVCQUVLQUFBQUxBQUFBQUFCQUFFQUFBSUNSQUVBT3c9PQ==ZGF0YTppbWFnZS9naWY7YmFzZTY0LFIwbEdPRGxoQVFBQkFQQUJBUC8vL3dBQUFDSDVCQUVLQUFBQUxBQUFBQUFCQUFFQUFBSUNSQUVBT3c9PQ==

我們得到的實際上是一個ArrayList的子類的引用,雖然這個子類相比ArrayList並沒有任何功能上的改變。

可以認為這是個本身裝有數據的子類(因為它的數據來自於自身的初始化),而不是取得引用后再賦值。

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

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());

}

ZGF0YTppbWFnZS9naWY7YmFzZTY0LFIwbEdPRGxoQVFBQkFQQUJBUC8vL3dBQUFDSDVCQUVLQUFBQUxBQUFBQUFCQUFFQUFBSUNSQUVBT3c9PQ==ZGF0YTppbWFnZS9naWY7YmFzZTY0LFIwbEdPRGxoQVFBQkFQQUJBUC8vL3dBQUFDSDVCQUVLQUFBQUxBQUFBQUFCQUFFQUFBSUNSQUVBT3c9PQ==

注意:

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

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

ArrayList  friends=new ArrayList<>();

friends.add("tom");

friends.add("lin");

invite(friends);

如果不想要寫這個數組列表,可將其作為一個匿名列表,通過雙括號的方式為列表添加元素,這樣代碼更為簡潔。

invite(new ArrayList ()

{

{

add("tom");

add("lin");

}

})

外層“{}”創建了ArrayLIst的一個匿名子類,內層“{}”創建了一個對象構造塊。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值