Skip to content

Commit 29d6d73

Browse files
authored
Merge pull request giantray#76 from AcceptedBoy/master
add->efficiency-of-java-double-brace-initialization.md
2 parents 9ca39a5 + af78212 commit 29d6d73

File tree

1 file changed

+202
-0
lines changed

1 file changed

+202
-0
lines changed
Lines changed: 202 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,202 @@
1+
## "Double Brace Initialization"的效率问题
2+
3+
#### 问题
4+
5+
`Double Brace Initialization`是java的隐藏特性,它有着如下诱人的语法:
6+
7+
```java
8+
Set<String> flavors = new HashSet<String>() {{
9+
add("vanilla");
10+
add("strawberry");
11+
add("chocolate");
12+
add("butter pecan");
13+
}};
14+
```
15+
16+
但是,这个特性听说不是很高效率,是否要限制一次性使用?
17+
18+
#### 回答
19+
20+
当我使用匿名内部类时出现了如下的问题:
21+
22+
```Auto
23+
2009/05/27 16:35 1,602 DemoApp2$1.class
24+
2009/05/27 16:35 1,976 DemoApp2$10.class
25+
2009/05/27 16:35 1,919 DemoApp2$11.class
26+
2009/05/27 16:35 2,404 DemoApp2$12.class
27+
2009/05/27 16:35 1,197 DemoApp2$13.class
28+
29+
/* snip */
30+
31+
2009/05/27 16:35 1,953 DemoApp2$30.class
32+
2009/05/27 16:35 1,910 DemoApp2$31.class
33+
2009/05/27 16:35 2,007 DemoApp2$32.class
34+
2009/05/27 16:35 926 DemoApp2$33$1$1.class
35+
2009/05/27 16:35 4,104 DemoApp2$33$1.class
36+
2009/05/27 16:35 2,849 DemoApp2$33.class
37+
2009/05/27 16:35 926 DemoApp2$34$1$1.class
38+
2009/05/27 16:35 4,234 DemoApp2$34$1.class
39+
2009/05/27 16:35 2,849 DemoApp2$34.class
40+
41+
/* snip */
42+
43+
2009/05/27 16:35 614 DemoApp2$40.class
44+
2009/05/27 16:35 2,344 DemoApp2$5.class
45+
2009/05/27 16:35 1,551 DemoApp2$6.class
46+
2009/05/27 16:35 1,604 DemoApp2$7.class
47+
2009/05/27 16:35 1,809 DemoApp2$8.class
48+
2009/05/27 16:35 2,022 DemoApp2$9.class
49+
```
50+
51+
这是在我的一个简单应用中所产生的类信息。在这个应用中,使用了大量的匿名内部类,这些类会被单独地编译成`class`文件。
52+
53+
`Double Brace Initialization`是一个带有实例初始化块的匿名内部类。这就意味着每一个新的类的产生都会执行一次实例块,这样的目的通常是为了创建一个简单的对象。
54+
55+
java虚拟机在使用类之前需要去读取其classes信息,然后执行字节码校验等流程。所以为了保存这些`class`文件,所需要的磁盘空间会增大。
56+
57+
这个可以说是`Double Brace Initialization`的开销。所以尽量不要过分使用。
58+
59+
---
60+
61+
在java的介绍中,`Double Brace Initialization`有着如下的写法:
62+
63+
```java
64+
List<String> list = new ArrayList<String>() {{
65+
add("Hello");
66+
add("World!");
67+
}};
68+
```
69+
70+
看起来像是java的隐藏特性,其实它只是下面代码的一个重写:
71+
72+
```java
73+
List<String> list = new ArrayList<String>() {
74+
75+
// 实例初始化块
76+
{
77+
add("Hello");
78+
add("World!");
79+
}
80+
};
81+
```
82+
83+
所以,它只是在匿名内部类中加上了实例初始化块而已。
84+
85+
---
86+
87+
Joshua Bloch希望以后的集合代码能够像这样简介:
88+
89+
```java
90+
List<Integer> intList = [1, 2, 3, 4];
91+
92+
Set<String> strSet = {"Apple", "Banana", "Cactus"};
93+
94+
Map<String, Integer> truthMap = { "answer" : 42 };
95+
```
96+
97+
但目前还没有这样的语法。
98+
99+
---
100+
101+
<strong>实践</strong>
102+
103+
做一个简单的试验:创建1000个带着`"Hello"``"World!"`元素的`ArrayList`
104+
105+
* 方法1:Double Brace Initialization
106+
107+
```
108+
List<String> l = new ArrayList<String>() {{
109+
add("Hello");
110+
add("World!");
111+
}};
112+
```
113+
114+
* 方法2:初始化`ArrayList`并调用`add`方法
115+
116+
```java
117+
List<String> l = new ArrayList<String>();
118+
l.add("Hello");
119+
l.add("World!");
120+
```
121+
122+
我修改了java的源文件使之能够为每种上述方法分别创建出1000个实例
123+
124+
* 方法1的测试
125+
126+
```java
127+
class Test1 {
128+
public static void main(String[] s) {
129+
long st = System.currentTimeMillis();
130+
131+
List<String> l0 = new ArrayList<String>() {{
132+
add("Hello");
133+
add("World!");
134+
}};
135+
136+
List<String> l1 = new ArrayList<String>() {{
137+
add("Hello");
138+
add("World!");
139+
}};
140+
141+
/* snip */
142+
143+
List<String> l999 = new ArrayList<String>() {{
144+
add("Hello");
145+
add("World!");
146+
}};
147+
148+
System.out.println(System.currentTimeMillis() - st);
149+
}
150+
```
151+
152+
* 方法2的测试
153+
154+
```java
155+
class Test2 {
156+
public static void main(String[] s) {
157+
long st = System.currentTimeMillis();
158+
159+
List<String> l0 = new ArrayList<String>();
160+
l0.add("Hello");
161+
l0.add("World!");
162+
163+
List<String> l1 = new ArrayList<String>();
164+
l1.add("Hello");
165+
l1.add("World!");
166+
167+
/* snip */
168+
169+
List<String> l999 = new ArrayList<String>();
170+
l999.add("Hello");
171+
l999.add("World!");
172+
173+
System.out.println(System.currentTimeMillis() - st);
174+
}
175+
}
176+
```
177+
178+
然后得出了下面的测试时间:
179+
180+
```Auto
181+
Test1 Times (ms) Test2 Times (ms)
182+
---------------- ----------------
183+
187 0
184+
203 0
185+
203 0
186+
188 0
187+
188 0
188+
187 0
189+
203 0
190+
188 0
191+
188 0
192+
203 0
193+
```
194+
195+
从上面我们可以看到,`Double Brace Initialization`平均时间花费了190ms左右。
196+
同时,另外一种方法平均只用了0ms。
197+
198+
所以,在第一个方法测试程序中,即`Double Brace Initialization`产生了1000个`class`文件。
199+
200+
## StackOverflow地址
201+
202+
[http://stackoverflow.com/questions/924285/efficiency-of-java-double-brace-initialization](http://stackoverflow.com/questions/924285/efficiency-of-java-double-brace-initialization)

0 commit comments

Comments
 (0)