提问人:yanchenko 提问时间:10/27/2008 最后编辑:Communityyanchenko 更新时间:12/26/2017 访问量:11023
什么时候应该使用基元而不是包装对象?
When should I use primitives instead of wrapping objects?
答:
是的,基元比对象快。 从 java 5 开始,您甚至可以混合原语和对象,而无需手动将一个对象转换为另一个对象。 自动装箱机制正好可以解决这个问题。
这意味着,如果将基元放入集合中,编译器将不会抱怨,并将基元隐式转换为对象。
评论
使用基元时速度更快,因为对象在使用前需要拆箱;因此,VM 需要执行一个额外的步骤。例如,为了对 Integer 执行算术运算,必须先将其转换为 int,然后才能执行算术运算。
在许多业务应用程序中,这可能无关紧要。但是,如果你正在写一些非常笨拙的东西,比如图形转换处理器,你更有可能关心。
我想说的是,只有当您分析应用程序并看到自动装箱是性能或内存问题时,您才应该担心使用基元而不是包装器。根据我的经验,在谈论基元与包装对象时,内存在 CPU 周期之前成为一个问题。
评论
不要忘记,由于为每个装箱事件创建一个新的包装器是相当昂贵的,特别是考虑到它通常用于方法的单个范围,因此自动装箱使用一个通用包装器池。
这实际上是蝇量级设计模式的实现。当已知值发生装箱时,不会创建新的包装器实例,而是从池中提取并返回预先创建的实例。
一个后果是:仍然不建议使用自动装箱进行科学计算。例如,代码 d = a * b + c 使用 a、b、c 和 d 的整数类,生成的代码为 d.valueOf(a.intValue() * b.intValue() + c.intValue())。所有这些方法调用都有其自身的开销,因此通常建议在需要将基元存储在集合中时使用自动装箱。
即便如此,如果您有大量的 Integer 包装 int,开销可能意味着更长的执行时间,最多 20 倍,如本文所述。
Jb 补充了以下重要评论:
此外,Wrapper.valueOf(primitive) 使用包装池。所以更喜欢 Integer.valueOf(5) 而不是新的 Integer(5)
评论
如果您需要将基元存储在集合中,则可以使用 commons-primitives。
我更喜欢使用原语而不是包装器,只有绝对需要包装器的地方是实体类。数据库支持 null,因此实体也应该支持 null。
我曾经做过一个在数据库访问中使用原语(和自制 ORM)的项目:
class Foo{
int xxx = -1;
...
}
然后你有:
void persist(Foo foo){
...
statement.setInt(15,foo.getXXX()==-1?null:foo.getXXX());
...
}
天哪,这是邪恶的。
评论