15

其实这里有一个类似的题目,实用价值不大。据我了解,原语性能更好,应该在任何地方使用,除了需要与对象相关的功能(例如null检查)的情况。对?

4

5 回答 5

23

不要忘记,由于为每个装箱事件创建一个新包装器非常昂贵,特别是考虑到它通常在方法的单个范围内使用,因此自动装箱使用一个通用包装器池。

这实际上是享元设计模式的一种实现。当一个众所周知的值发生装箱时,不是创建一个新的包装器实例,而是从池中获取一个预先创建的实例并返回。

一个后果是:仍然不建议使用自动装箱进行科学计算。例如,代码 d = a * b + c 对 a、b、c 和 d 使用 Integer 类,生成的代码为 d.valueOf(a.intValue() * b.intValue() + c.intValue( ))。所有这些方法调用都有自己的开销,因此通常建议在需要将原语存储在集合中时使用自动装箱

即使这样,如果您有大量的 Integer 包装 int 集合,开销可能意味着更长的执行时间,最多20 倍,如本文所述


Jb 添加了这个重要的评论:

Wrapper.valueOf(primitive) 也使用包装池。所以更喜欢 Integer.valueOf(5) 到 new Integer(5)

于 2008-10-27T11:23:31.130 回答
10

图元在使用时速度更快因为对象在使用前需要拆箱;因此,VM 需要执行一个额外的步骤。例如,为了对 Integer 执行算术运算,必须首先将其转换为 int 才能执行算术运算。

在许多业务应用程序中,这可能并不重要。但是,如果您正在编写一些非常繁重的东西,例如图形转换处理器,那么您更有可能关心。

于 2008-10-27T11:12:13.290 回答
5

是的,原语比对象快。从 java 5 开始,您甚至可以混合原语和对象,而无需手动将其转换为另一种。自动装箱机制就可以解决这个问题。

这意味着如果您将原语放入集合中,编译器不会抱怨,而是将原语隐式转换为对象。

于 2008-10-27T11:04:21.980 回答
1

我想说,只有当您分析应用程序并看到自动装箱是性能或内存问题时,您才应该担心使用原语而不是包装器。根据我的经验,在谈论原语与包装对象时,内存在 CPU 周期之前就成为一个问题。

于 2008-10-27T11:12:20.420 回答
1

如果您需要在集合中存储原语,您可以使用commons-primitives

我更喜欢使用原语来包装,只有绝对需要包装的地方是实体类。数据库支持空值,所以实体也应该支持。

我曾经参与过在数据库访问中使用原语(和自制 ORM)的项目:

 class Foo{
    int xxx = -1;
 ...
 }

然后你有:

 void persist(Foo foo){
     ...
     statement.setInt(15,foo.getXXX()==-1?null:foo.getXXX());
     ...
}

上帝是邪恶的。

于 2008-10-27T12:25:09.697 回答