【问题标题】:Method invokes inefficient new Integer(int) constructor; use Integer.valueOf(int) instead方法调用效率低下的 new Integer(int) 构造函数;改用 Integer.valueOf(int)
【发布时间】:2014-08-28 18:04:07
【问题描述】:

我的目标是优化我的应用程序代码。我的代码如下所示:

int a = 10;
Map<String , Integer> myMap = new TreeMap<>();

myMap.put("first" , new Integer(a)); //[FindBugs] Method com.abc.xyz.Test.main(String[]) invokes inefficient new Integer(int) constructor; use Integer.valueOf(int) instead 

当我在 Netbeans 中通过 Findbugs 进行静态分析时,它显示存在类似“方法调用效率低下的新 Integer(int) 构造函数;请改用 Integer.valueOf(int)”的警告/错误.

我知道 new Integer(int)Integer.valueOf(int) 之间的区别。

一个创建一个额外的对象,另一个不创建。还有一个不缓存,另一个缓存。

所以我已经像这样修改了我的代码......

m.put("first" , Integer.valueOf(a)); // Unnecessary boxing to Integer

但同样也会发出警告“Innecessary boxing to Integer”(由编辑器而非 findbugs)。

所以,我又改成这样了......

m.put("first" , a); //No warning at all...

最终完全没有警告

我的问题:

1.) 这个link 建议在内部(通过编译器) m.put("first" , a); 正在转换 m.put("first" , Integer .valueOf(a));

(在那个例子中,有一个 List-ArrayList,这里我们有 Map-TreeMap...仅供参考)。 那为什么编辑器会发出警告? 我该怎么办?优化的方式是什么?

2.) 如果不是Map,如果有像HashTable这样的数据结构,那么???

3.) 为什么编辑器对整数进行不必要的装箱

4.) 为什么 m.put("first" , a) 有效?因为我正在传递原始变量,而map 的put() 只接受Object。那么是不是因为自动装箱

【问题讨论】:

  • 是的,这是由于自动装箱。
  • OK.thanks...那么优化的好方法是什么?最后一个??
  • 我不认为你可以优化它,自动装箱为你做同样的工作,所以你不需要明确地做valueOf(a)

标签: java findbugs autoboxing


【解决方案1】:

1.) 此链接建议在内部(由编译器) m.put("first" , a);正在转换 m.put("first" , Integer.valueOf(a));

(在那个例子中,有一个 List-ArrayList,这里我们有 Map-TreeMap...仅供参考)。那为什么编辑器会发出警告?我该怎么办?优化的方式是什么?

是的,编译器知道m.put("first", a) 只接受对象,因此应用了自动装箱。在性能方面,使用自动装箱或写 Integer.valueOf(a) 不会有任何区别。

另一方面,new Integer(a) 并不比Integer.valueOf(a) 慢。不同之处在于对于小的绝对值(默认值为 -128 到 127)Integer.valueOf(a) 将使用缓存,即不会一直创建新对象。对于所有其他值,它无论如何都会调用new Integer(a)

例子:

Integer.valueOf(1) == Integer.valueOf(1) 将返回 true
Integer.valueOf(1000) == Integer.valueOf(1000) 将返回 false
new Integer(1) == new Integer(1) 将返回 false,因为此处未使用缓存

2.) 如果不是Map,如果有HashTable这样的数据结构,那么???

你为什么这么问?有HashTable,但由于它是同步的,这意味着比HashMap 更多的开销,所以除非你需要同步,否则如果你需要排序,请坚持HashMapTreeMap

3.) 为什么编辑器给 Integer 提供不必要的装箱。

这可能只是因为可读性(aInteger.valueOf(a) 短)。

4.) 为什么 m.put("first" , a) 有效?因为我传递原始变量和地图的 put() 只接受对象。那么是因为自动装箱吗?

见 1

【讨论】:

  • 谢谢托马斯...你解决了我的疑问。我的想法相同,但不确定两者是否相同...是的,在阅读过程中,我了解了 -128 到 127 的缓存范围...+1 表示平等...
  • 所以不能盲目优化。 (如果图片中有一些参考比较或equals(),更改为Integer.valueOf(int)可能会导致麻烦)对???
  • @MananShah 是的,盲目优化几乎不是一个好主意。 :) equals() 应该是个问题,因为它应该总是产生相同的结果,但是对象相等(即 == )可能是个问题。通常使用 == 时应谨慎使用,并且仅在确实需要时使用。
【解决方案2】:

4.) 为什么 m.put("first" , a) 有效?因为我传递原始变量和地图的 put() 只接受对象。

自动装箱。

int 会自动转换为 Integer,反之亦然(在这种情况下可能会出现 NullPointerException)

3.) 为什么编辑器给 Integer 提供不必要的装箱。

因为您不需要编写这段代码。编译器会为你做这件事。

它通常更具可读性

2.) 如果不是Map,如果有HashTable这样的数据结构,那么大小写是一样的???

是的,在 JDK 集合中仅适用于对象。这意味着必须将原始类型装箱。它具有很小的运行时成本和巨大的内存开销。 Integer 比 int 占用大约 300% 的内存。

你无法逃脱它。避免装箱开销的唯一方法是使用专门的集合,如 GNU trove,它为每个原始类型提供一个类。仅当您计划将数百万个原始元素存储到集合中时才有用。

最后永远不要写 new Integer(x)。 Integer.valueOf(x) 做同样的事情,但它维护一个内部缓存以避免为一些常用值创建新实例。

【讨论】:

  • 感谢您记住 NullPointerException 和代码可读性。我不知道 GNU trove 的事情......我肯定会读它......我也不知道 Integer = 300% int 在内存方面...... :) 很好。再次感谢。
  • 由于问题 1,我已接受 thomas 的回答...抱歉,我们只能接受一个答案。
猜你喜欢
  • 2015-12-24
  • 1970-01-01
  • 2011-09-28
  • 2016-11-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-05-30
相关资源
最近更新 更多