<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          這樣創(chuàng)建集合了,非常容易內(nèi)存泄露

          共 4426字,需瀏覽 9分鐘

           ·

          2021-12-31 03:04



          由于Java語言的集合框架中(collections, 如list, map, set等)沒有提供任何簡便的語法結(jié)構(gòu),這使得在建立常量集合時(shí)的工作非常繁索。每次建立時(shí)我們都要做:
          1、定義一個(gè)空的集合類變量?
          2、向這個(gè)結(jié)合類中逐一添加元素?
          3、將集合做為參數(shù)傳遞給方法
          例如,要將一個(gè)Set變量傳給一個(gè)方法:
          Set?users?=?new?HashSet();

          users.add("Hollis");

          users.add("hollis");

          users.add("HollisChuang");

          users.add("hollis666");

          transferUsers(users);

          這樣的寫法稍微有些復(fù)雜,有沒有簡潔的方式呢?




          雙括號(hào)語法初始化集合


          其實(shí)有一個(gè)比較簡潔的方式,那就是雙括號(hào)語法double-brace syntax)建立并初始化一個(gè)新的集合:

          ????public?class?DoubleBraceTest?{

          ????????public?static?void?main(String[]?args)?{

          ????????????Set?users?=?new?HashSet()?{{

          ????????????????add("Hollis");

          ????????????????add("hollis");

          ????????????????add("HollisChuang");

          ????????????????add("hollis666");

          ????????????}};

          ????????}

          ????}

          同理,創(chuàng)建并初始化一個(gè)HashMap的語法如下:

          ????Map?users?=?new?HashMap<>()?{{

          ????????put("Hollis","Hollis");

          ????????put("hollis","hollis");

          ????????put("HollisChuang","HollisChuang");

          ????}};

          不只是Set、Map,jdk中的集合類都可以用這種方式創(chuàng)建并初始化。

          當(dāng)我們使用這種雙括號(hào)語法初始化集合類的時(shí)候,在對(duì)Java文件進(jìn)行編譯時(shí),可以發(fā)現(xiàn)一個(gè)奇怪的現(xiàn)象,使用javac對(duì)DoubleBraceTest進(jìn)行編譯:

          javac?DoubleBraceTest.java

          我們會(huì)發(fā)現(xiàn),得到兩個(gè)class文件:

          DoubleBraceTest.class

          DoubleBraceTest$1.class

          有經(jīng)驗(yàn)的朋友可能一看到這兩個(gè)文件就會(huì)知道,這里面一定用到了匿名內(nèi)部類。

          沒錯(cuò),使用這個(gè)雙括號(hào)初始化的效果是創(chuàng)建匿名內(nèi)部類。創(chuàng)建的類有一個(gè)隱式的this指針指向外部類。



          不建議使用這種形式
          首先,使用這種形式創(chuàng)建并初始化集合會(huì)導(dǎo)致很多內(nèi)部類被創(chuàng)建。因?yàn)槊看问褂秒p大括號(hào)初始化時(shí),都會(huì)生成一個(gè)新類。如這個(gè)例子:

          ????Map?hollis?=?new?HashMap(){{

          ????????put("firstName",?"Hollis");

          ????????put("lastName",?"Chuang");

          ????????put("contacts",?new?HashMap(){{

          ????????????put("0",?new?HashMap(){{

          ????????????????put("blogs",?"http://www.hollischuang.com");

          ????????????}});

          ????????????put("1",?new?HashMap(){{

          ????????????????put("wechat",?"hollischuang");

          ????????????}});

          ????????}});

          ????}};

          這會(huì)使得很多內(nèi)部類被創(chuàng)建出來:

          ????DoubleBraceTest$1$1$1.class

          ????DoubleBraceTest$1$1$2.class

          ????DoubleBraceTest$1$1.class

          ????DoubleBraceTest$1.class

          ????DoubleBraceTest.class

          這些內(nèi)部類被創(chuàng)建出來,是需要被類加載器加載的,這就帶來了一些額外的開銷。

          如果您使用上面的代碼在一個(gè)方法中創(chuàng)建并初始化一個(gè)map,并從方法返回該map,那么該方法的調(diào)用者可能會(huì)毫不知情地持有一個(gè)無法進(jìn)行垃圾收集的資源。

          ????public?Map?getMap()?{

          ????????Map?hollis?=?new?HashMap(){{

          ????????????put("firstName",?"Hollis");

          ????????????put("lastName",?"Chuang");

          ????????????put("contacts",?new?HashMap(){{

          ????????????????put("0",?new?HashMap(){{

          ????????????????????put("blogs",?"http://www.hollischuang.com");

          ????????????????}});

          ????????????????put("1",?new?HashMap(){{

          ????????????????????put("wechat",?"hollischuang");

          ????????????????}});

          ????????????}});

          ????????}};

          ????????return?hollis;

          ????}

          我們嘗試通過調(diào)用getMap得到這樣一個(gè)通過雙括號(hào)初始化出來的map

          ????public?class?DoubleBraceTest?{

          ????????public?static?void?main(String[]?args)?{

          ????????????DoubleBraceTest?doubleBraceTest?=?new?DoubleBraceTest();

          ????????????Map?map?=?doubleBraceTest.getMap();

          ????????}

          ????}

          返回的Map現(xiàn)在將包含一個(gè)對(duì)DoubleBraceTest的實(shí)例的引用。讀者可以嘗試這通過debug或者以下方式確認(rèn)這一事實(shí)。

          Field?field?=?map.getClass().getDeclaredField("this$0");

          field.setAccessible(true);

          System.out.println(field.get(map).getClass());




          替代方案


          很多人使用雙括號(hào)初始化集合,主要是因?yàn)樗容^方便,可以在定義集合的同時(shí)對(duì)他進(jìn)行初始化。
          但其實(shí),目前已經(jīng)有很多方案可以做這個(gè)事情了,不需要再使用這種存在風(fēng)險(xiǎn)的方案。

          使用Arrays工具類

          當(dāng)我們想要初始化一個(gè)List的時(shí)候,可以借助Arrays類,Arrays中提供了asList可以把一個(gè)數(shù)組轉(zhuǎn)換成List:

          ??List?list2?=?Arrays.asList("hollis?",?"Hollis",?"HollisChuang");

          但是需要注意的是,asList 得到的只是一個(gè) Arrays 的內(nèi)部類,是一個(gè)原來數(shù)組的視圖 List,因此如果對(duì)它進(jìn)行增刪操作會(huì)報(bào)錯(cuò)。

          使用Stream

          Stream是Java中提供的新特性,他可以對(duì)傳入流內(nèi)部的元素進(jìn)行篩選、排序、聚合等中間操作(intermediate operate),最后由最終操作(terminal operation)得到前面處理的結(jié)果。
          我們可以借助Stream來初始化集合:java

          List?list1?=?Stream.of("hollis",?"Hollis",?"HollisChuang").collect(Collectors.toList());

          使用第三方工具類

          很多第三方的集合工具類可以實(shí)現(xiàn)這個(gè)功能,如Guava等:

          ImmutableMap.of("k1",?"v1",?"k2",?"v2");

          ImmutableList.of("a",?"b",?"c",?"d");

          關(guān)于Guava和其中定義的不可變集合,我們后面會(huì)再詳細(xì)介紹

          Java 9內(nèi)置方法

          其實(shí)在Java 9 中,在List、Map等集合類中已經(jīng)內(nèi)置了初始化的方法,如List中包含了12個(gè)重載的of方法,就是來做這個(gè)事情的:

          ????/**

          ?????*?Returns?an?unmodifiable?list?containing?zero?elements.

          ?????*

          ?????*?See?Unmodifiable?Lists?for?details.

          ?????*

          ?????*?@param??the?{@code?List}'s?element?type

          ?????*?@return?an?empty?{@code?List}

          ?????*

          ?????*?@since?9

          ?????*/


          ????static??List?of()?{

          ????????return?ImmutableCollections.emptyList();

          ????}



          ????static??List?of(E?e1)?{

          ????????return?new?ImmutableCollections.List12<>(e1);

          ????}



          ????static??List?of(E...?elements)?{

          ????????switch?(elements.length)?{?//?implicit?null?check?of?elements

          ????????????case?0:

          ????????????????return?ImmutableCollections.emptyList();

          ????????????case?1:

          ????????????????return?new?ImmutableCollections.List12<>(elements[0]);

          ????????????case?2:

          ????????????????return?new?ImmutableCollections.List12<>(elements[0],?elements[1]);

          ????????????default:

          ????????????????return?new?ImmutableCollections.ListN<>(elements);

          ????????}

          ????}

          瀏覽 14
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  日本黄色视频网站大全 | 亚洲 日韩 中文字幕 | 水多多成人免费A片 | 亚洲 小说区 图片区 | 91精品福利 |