由于Java語言的集合框架中(collections, 如list, map, set等)沒有提供任何簡便的語法結(jié)構(gòu),這使得在建立常量集合時的工作非常繁索。每次建立時我們都要做:
定義一個臨時的集合類變量 建立一個空集合的實例,然后賦值給變量 將數(shù)據(jù)放入集合中 最后將集合做為參數(shù)傳遞給方法
例如,要將一個Set變量傳給一個方法:
1
2
3
4
5
6
|
Set validCodes = new HashSet(); validCodes.add( "XZ13s" ); validCodes.add( "AB21/X" ); validCodes.add( "YYLEX" ); validCodes.add( "AR2D" ); removeProductsWithCodeIn(validCodes); |
也可以用靜態(tài)初始的方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
private static final Set validCodes = new HashSet(); static { validCodes.add( "XZ13s" ); validCodes.add( "AB21/X" ); validCodes.add( "YYLEX" ); validCodes.add( "AR2D" ); } private static final Set validCodes = new HashSet(); static { validCodes.add( "XZ13s" ); validCodes.add( "AB21/X" ); validCodes.add( "YYLEX" ); validCodes.add( "AR2D" ); } |
其實,還有簡結(jié)的方法,我們可以用雙括弧語法(double-brace syntax)建立并初始化一個新的集合:
1
2
3
4
5
6
7
8
9
10
11
12
|
private static final Set VALID_CODES = new HashSet() {{ add( "XZ13s" ); add( "AB21/X" ); add( "YYLEX" ); add( "AR2D" ); }}; private static final Set VALID_CODES = new HashSet() {{ add( "XZ13s" ); add( "AB21/X" ); add( "YYLEX" ); add( "AR2D" ); }}; |
或者
1
2
3
4
5
6
7
8
9
10
11
12
|
removeProductsWithCodeIn( new HashSet() {{ add( "XZ13s" ); add( "AB21/X" ); add( "YYLEX" ); add( "AR5E" ); }}); removeProductsWithCodeIn( new HashSet() {{ add( "XZ13s" ); add( "AB21/X" ); add( "YYLEX" ); add( "AR5E" ); }}); |
第一層括弧 實際是定義了一個內(nèi)部匿名類 (Anonymous Inner Class),第二層括弧 實際上是一個實例初始化塊 (instance initializer block),這個塊在內(nèi)部匿名類構(gòu)造時被執(zhí)行。這個塊之所以被叫做“實例初始化塊”是因為它們被定義在了一個類的實例范圍內(nèi)。這和“靜態(tài)初始化塊 (static initialzer)”不同,因為這種塊在定義時在括弧前使用了static關(guān)鍵字,因此它的和類在同一個范圍內(nèi)的,也就是說當(dāng)類加載時就會被執(zhí)行
實例初始化塊中可以使用其容器范圍內(nèi)的所有方法及變量,但特別需要注意的是實例初始化塊是在構(gòu)造器之前運行的。
這種方法只適用于不是final的類,因為final類是無法建立內(nèi)部匿名子類,好在集合類都沒有這個限制。因此,這種方法還可以被用來初始化其它任何對象,比如一個GUI對象:
1
2
3
4
5
6
7
8
9
10
11
12
|
add( new JPanel() {{ setLayout(...); setBorder(...); add( new JLabel(...)); add( new JSpinner(...)); }}); add( new JPanel() {{ setLayout(...); setBorder(...); add( new JLabel(...)); add( new JSpinner(...)); }}); |
這樣建立的內(nèi)部匿名類的實例中包函它容器對像的引用。如果串行化(serialization)這個集合同時也會串行化它的內(nèi)部類。
另外,這種雙括號初始化的方式針對map的初始化工作可以減少很多代碼,請看:
1
2
3
4
5
6
7
8
9
10
11
|
Map<String, Set<String>> baselineMap = new HashMap<>(); final String schema = "schema" ; if (baselineMap.get(type) == null ) { baselineMap.put(type, new HashSet<String>() {{ add(schema); }}); } else { baselineMap.put(type, new HashSet<String>(baselineMap.get(type)) {{ add(schema); }}); } |
這段代碼我相信不用特別解釋,基本都能看懂,想想如果不用雙括號初始化的方式的話需要多寫多少行代碼!~
以上就是關(guān)于Java雙括弧初始化的技巧,提高了代碼的可讀性,而且簡化了代碼的數(shù)量,大家可以嘗試應(yīng)用到自己的項目中。