2

来自 PMD:

IntegerInstantiation:在 JDK 1.5 中,调用 new Integer() 会导致内存分配。Integer.valueOf() 对内存更友好。

ByteInstantiation:在 JDK 1.5 中,调用 new Byte() 会导致内存分配。Byte.valueOf() 对内存更友好。

ShortInstantiation:在 JDK 1.5 中,调用 new Short() 会导致内存分配。Short.valueOf() 对内存更友好。

LongInstantiation:在 JDK 1.5 中,调用 new Long() 会导致内存分配。Long.valueOf() 对内存更友好。

这同样适用于 JDK 1.6 吗?我只是想知道编译器或 jvm 是否将其优化为各自的valueof方法。

4

5 回答 5

3

理论上,编译器可以优化一部分使用(例如)new Integer(n)而不是推荐的Integer.valueOf(n).

==首先,我们应该注意,只有当编译器可以保证包装对象永远不会与使用or的其他对象进行比较时,才能应用优化!=。(如果发生这种情况,那么优化会改变包装对象的语义,使得“==”和“!=”的行为方式与 JLS 相悖。)

鉴于此,这种优化不太可能值得实施:

  1. 优化只会帮助那些忽略 javadoc 等建议的编写不佳的应用程序。对于编写良好的应用程序,测试是否可以应用优化只会减慢优化器的速度;例如 JIT 编译器。

  2. 即使对于编写不佳的应用程序,允许优化的位置的限制也意味着很少有实际调用new Integer(n)符合优化条件。new在大多数情况下,跟踪可能使用由表达式创建的包装器的所有位置的成本太高。如果您在图片中包含反射,则除了局部变量之外几乎不可能进行跟踪。由于原始包装器的大多数用途都需要将它们放入集合中,因此很容易看出(通过实际的优化器)几乎不会允许优化。

  3. 即使在实际应用优化的情况下,它也只会对n有限范围内的值有所帮助。例如,调用Integer.valueOf(n)largen将始终创建一个新对象。

于 2010-07-24T01:07:14.357 回答
2

这也适用于 Java 6。使用 Java 6 尝试以下方法来证明这一点:

System.out.println(new Integer(3) == new Integer(3));
System.out.println(Integer.valueOf(3) == Integer.valueOf(3));

System.out.println(new Long(3) == new Long(3));
System.out.println(Long.valueOf(3) == Long.valueOf(3));

System.out.println(new Byte((byte)3) == new Byte((byte)3));
System.out.println(Byte.valueOf((byte)3) == Byte.valueOf((byte)3));

然而,正如预期的那样,随着数量的增加,优化就会关闭。

于 2010-07-24T00:33:30.847 回答
1

这同样适用于 Java SE 6。一般来说,很难优化新对象的创建。可以保证,比如说,new Integer(42) != new Integer(42)。在某些情况下有可能完全消除获取对象的需要,但我相信在撰写本文时,HotSpot 生产版本中已禁用的所有内容。

于 2010-07-24T00:31:27.857 回答
0

大多数时候都无所谓。除非您已确定您正在运行一段被多次调用的关键代码(例如 10K 或更多),否则它可能不会产生太大影响。

如果有疑问,假设编译器没有优化。它实际上很少。然而,JVM 可以做很多优化,但消除创建对象的需要并不是其中之一。一般假设是对象分配在大多数情况下都足够快。

注意:只运行几次的代码(默认情况下小于 10K 时间)甚至不会完全编译为本机代码,这可能会比对象分配更慢你的代码。

于 2010-07-24T07:35:25.090 回答
0

在最近的带有逃逸分析和标量替换的 jvm 上,new Integer()实际上可能比Integer.valueOf()将变量的范围限制为一个方法或块时更快。有关更多详细信息,请参阅Java 中的自动装箱与手动装箱。

于 2010-07-24T16:28:09.770 回答