自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

千萬不要再這樣創(chuàng)建集合了!極容易內(nèi)存泄露!

安全 應(yīng)用安全
由于Java語言的集合框架中(collections, 如list, map, set等)沒有提供任何簡便的語法結(jié)構(gòu),這使得在建立常量集合時(shí)的工作非常繁索。

[[426021]]

由于Java語言的集合框架中(collections, 如list, map, set等)沒有提供任何簡便的語法結(jié)構(gòu),這使得在建立常量集合時(shí)的工作非常繁索。每次建立時(shí)我們都要做:

1、定義一個(gè)空的集合類變量

2、向這個(gè)結(jié)合類中逐一添加元素

3、將集合做為參數(shù)傳遞給方法

例如,要將一個(gè)Set變量傳給一個(gè)方法:

  1. Set users = new HashSet(); 
  2.  
  3. users.add("Hollis"); 
  4.  
  5. users.add("hollis"); 
  6.  
  7. users.add("HollisChuang"); 
  8.  
  9. users.add("hollis666"); 
  10.  
  11. transferUsers(users); 

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

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

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

  1. public class DoubleBraceTest { 
  2.  
  3.      public static void main(String[] args) { 
  4.  
  5.          Set users = new HashSet() {{ 
  6.  
  7.              add("Hollis"); 
  8.  
  9.              add("hollis"); 
  10.  
  11.              add("HollisChuang"); 
  12.  
  13.              add("hollis666"); 
  14.  
  15.          }}; 
  16.  
  17.      } 
  18.  
  19.  } 

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

  1. Map<String,String> users = new HashMap<>() {{ 
  2.  
  3.     put("Hollis","Hollis"); 
  4.  
  5.     put("hollis","hollis"); 
  6.  
  7.     put("HollisChuang","HollisChuang"); 
  8.  
  9. }}; 

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

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

  1. javac DoubleBraceTest.java 

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

  1. DoubleBraceTest.class 
  2.  
  3. 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è)例子:

  1. Map hollis = new HashMap(){{ 
  2.  
  3.     put("firstName""Hollis"); 
  4.  
  5.     put("lastName""Chuang"); 
  6.  
  7.     put("contacts", new HashMap(){{ 
  8.  
  9.         put("0", new HashMap(){{ 
  10.  
  11.             put("blogs""http://www.hollischuang.com"); 
  12.  
  13.         }}); 
  14.  
  15.         put("1", new HashMap(){{ 
  16.  
  17.             put("wechat""hollischuang"); 
  18.  
  19.         }}); 
  20.  
  21.     }}); 
  22.  
  23. }}; 

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

  1. DoubleBraceTest$1$1$1.class 
  2.  
  3.  DoubleBraceTest$1$1$2.class 
  4.  
  5.  DoubleBraceTest$1$1.class 
  6.  
  7.  DoubleBraceTest$1.class 
  8.  
  9.  DoubleBraceTest.class 

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

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

  1. public Map getMap() { 
  2.  
  3.      Map hollis = new HashMap(){{ 
  4.  
  5.          put("firstName""Hollis"); 
  6.  
  7.          put("lastName""Chuang"); 
  8.  
  9.          put("contacts", new HashMap(){{ 
  10.  
  11.              put("0", new HashMap(){{ 
  12.  
  13.                  put("blogs""http://www.hollischuang.com"); 
  14.  
  15.              }}); 
  16.  
  17.              put("1", new HashMap(){{ 
  18.  
  19.                  put("wechat""hollischuang"); 
  20.  
  21.              }}); 
  22.  
  23.          }}); 
  24.  
  25.      }}; 
  26.  
  27.      return hollis; 
  28.  
  29.  } 

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

  1. public class DoubleBraceTest { 
  2.  
  3.       public static void main(String[] args) { 
  4.  
  5.           DoubleBraceTest doubleBraceTest = new DoubleBraceTest(); 
  6.  
  7.           Map map = doubleBraceTest.getMap(); 
  8.  
  9.       } 
  10.  
  11.   } 

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

  1. Field field = map.getClass().getDeclaredField("this$0"); 
  2.  
  3. field.setAccessible(true); 
  4.  
  5. System.out.println(field.get(map).getClass()); 

替代方案

很多人使用雙括號(hào)初始化集合,主要是因?yàn)樗容^方便,可以在定義集合的同時(shí)對他進(jìn)行初始化。

但其實(shí),目前已經(jīng)有很多方案可以做這個(gè)事情了,不需要再使用這種存在風(fēng)險(xiǎn)的方案。

使用Arrays工具類

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

  1. List<String> list2 = Arrays.asList("hollis ""Hollis""HollisChuang"); 

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

使用Stream

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

我們可以借助Stream來初始化集合:java

  1. List<String> list1 = Stream.of("hollis""Hollis""HollisChuang").collect(Collectors.toList()); 

使用第三方工具類

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

  1. ImmutableMap.of("k1""v1""k2""v2"); 
  2.  
  3. ImmutableList.of("a""b""c""d"); 

關(guān)于Guava和其中定義的不可變集合,我們在第19章節(jié)中會(huì)詳細(xì)介紹

Java 9內(nèi)置方法

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

  1. /** 
  2.  
  3.   * Returns an unmodifiable list containing zero elements. 
  4.  
  5.   * 
  6.  
  7.   * See <a href="#unmodifiable">Unmodifiable Lists</a> for details. 
  8.  
  9.   * 
  10.  
  11.   * @param <E> the {@code List}'s element type 
  12.  
  13.   * @return an empty {@code List} 
  14.  
  15.   * 
  16.  
  17.   * @since 9 
  18.  
  19.   */ 
  20.  
  21.  static <E> List<E> of() { 
  22.  
  23.      return ImmutableCollections.emptyList(); 
  24.  
  25.  } 
  26.  
  27.  
  28.  
  29.  static <E> List<E> of(E e1) { 
  30.  
  31.      return new ImmutableCollections.List12<>(e1); 
  32.  
  33.  } 
  34.  
  35.  
  36.  
  37.  static <E> List<E> of(E... elements) { 
  38.  
  39.      switch (elements.length) { // implicit null check of elements 
  40.  
  41.          case 0: 
  42.  
  43.              return ImmutableCollections.emptyList(); 
  44.  
  45.          case 1: 
  46.  
  47.              return new ImmutableCollections.List12<>(elements[0]); 
  48.  
  49.          case 2: 
  50.  
  51.              return new ImmutableCollections.List12<>(elements[0], elements[1]); 
  52.  
  53.          default
  54.  
  55.              return new ImmutableCollections.ListN<>(elements); 
  56.  
  57.      } 
  58.  
  59.  } 

 

責(zé)任編輯:武曉燕 來源: 51CTO專欄
相關(guān)推薦

2024-12-30 08:22:35

2020-04-03 08:30:44

RabbitMQKafka軟件

2019-11-18 10:16:37

工程師開發(fā)網(wǎng)絡(luò)

2019-11-18 10:05:43

程序員技能開發(fā)者

2015-04-27 09:12:04

JS魔法堂IE內(nèi)存泄露

2024-11-20 18:16:39

MyBatis批量操作數(shù)據(jù)庫

2013-08-19 11:03:21

微軟谷歌

2022-09-20 18:27:31

Kubernetes云服務(wù)

2012-03-14 14:25:57

2017-05-24 11:44:17

Linux命令

2019-04-03 14:03:58

Linux命令運(yùn)行

2019-03-11 15:26:26

HTTPSHTTP密鑰

2019-10-25 09:35:58

HTTPSHTTP通信

2019-11-13 09:08:50

HTTPS安全加密算法

2024-06-27 08:36:12

Lodash對象類型isObject?

2009-09-12 10:59:37

2019-11-28 18:51:07

PythonPHP編程語言

2012-03-28 22:06:15

Android

2020-05-09 10:18:31

Java開源工具

2020-07-09 14:40:31

程序員技能開發(fā)者
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)