You signed in with another tab or window.Reload to refresh your session.You signed out in another tab or window.Reload to refresh your session.You switched accounts on another tab or window.Reload to refresh your session.Dismiss alert
例如,Map 接口的 keySet 方法返回该 Map 对象的 Set 视图,其中包含该 Map 中所有的键(`key`)。表面看起来,好像每次调用 keySet 都应该创建一个新的 Set 实例,但是,对于一个给定的 Map 对象,实际上每次调用 keySet 方法都会返回同样的 Set 实例。虽然被返回的 Set 实例一般是可改变的,但是所有返回的对象在功能上是等同的:当其中一个返回对象发生变化的时候,所有其它的返回对象也要发生变化,因为它们是有同一个 Map 实例支撑的。虽然创建 keySet 视图对象的多个实例并无害处,却也是没有必要的。
340
+
341
+
在 Java 1.5 发行版本中,有一种创建多余对象的新方法,称为自动装箱(`autoboxing`),它允许程序员将基本类型和装箱基本类型(`Boxed Primitive Type`)混用,按需要自动装箱和拆箱。自动装箱使得基本类型和装箱基本类型的差别变得很模糊,但是并没有完全消除。它们在语义上有着微妙的差别,在性能上也有着比较明显的差别(见第 49 条)。考虑下面的程序,它计算所有 int 正值的总和。为此,程序必须使用 long 类型,因为 int 不够大,无法容纳所有 int 正值的总和:
342
+
343
+
```java
344
+
345
+
// Hideously slow program! Can you spot the object creation?
346
+
publicstaticvoid mian(String[] args) {
347
+
Long sum=0L;
348
+
for (long i=0; i<Integer.MAX_VALUE; i++) {
349
+
sum+= i;
350
+
}
351
+
System.out.println(sum);
352
+
}
353
+
354
+
```
355
+
356
+
这段程序程序算出的答案是正确的,但是比实际情况要更慢一些,只因为打错一个字符。变量 sum 被声明成 Long 而不是 long,意味着程序构造了大约 2^31 个多余的 Long 实例(大约每次往 Long sum 中增加 long 时构造一个实例)。将 sum 的声明从 Long 改成 long,运行时间从 43 秒减少到 6.8 秒。结论很明显:**要优先使用基本类型而不是装箱基本类型,要当心无意识的自动装箱。**