最近我看到了这样的Java代码:
myMethod(new Integer(123));
我目前正在重构一些代码,在Sonar工具中看到了一个提示,建议使用以下代码更加内存友好:
myMethod(Integer.valueOf(123));
然而在这种情况下,我认为如果我使用以下语句是没有区别的:
myMethod(123);
如果我传递变量给方法,我可以理解这一点,但硬编码整数?或者如果有Long/Double等类型,我想要一个数字的Long表示。但是整数呢?
最近我看到了这样的Java代码:
myMethod(new Integer(123));
我目前正在重构一些代码,在Sonar工具中看到了一个提示,建议使用以下代码更加内存友好:
myMethod(Integer.valueOf(123));
然而在这种情况下,我认为如果我使用以下语句是没有区别的:
myMethod(123);
如果我传递变量给方法,我可以理解这一点,但硬编码整数?或者如果有Long/Double等类型,我想要一个数字的Long表示。但是整数呢?
new Integer(123)
每次调用都会创建一个新的Object
实例。
根据javadoc,Integer.valueOf(123)
有一个不同之处,它缓存Object
,因此如果您调用它多次,可能会(也可能不会)得到相同的Object
。
例如,以下代码:
public static void main(String[] args) {
Integer a = new Integer(1);
Integer b = new Integer(1);
System.out.println("a==b? " + (a==b));
Integer c = Integer.valueOf(1);
Integer d = Integer.valueOf(1);
System.out.println("c==d? " + (c==d));
}
有以下输出:
a==b? false
c==d? true
如果你使用 int
值,那么你就是在使用原始类型(考虑到你的方法签名也使用了原始类型) - 它会使用稍少一点的内存,可能更快,但你无法将其添加到集合中。
此外,如果你的方法签名使用了 Integer
,也要看一下 Java 的 自动装箱 - 当你使用它时,JVM 会自动调用 Integer.valueOf()
方法(从而也使用缓存)。
Integer.valueOf()
,因此它确实使用缓存。 - Marcelonew Integer(234)
创建了一个与现有的 Integer.valueOf(234)
不同的对象,为什么 listIntegers.remove(new Integer(234));
会起作用呢? - Treefish Zhang
public static Integer valueOf(int i)
返回表示指定 int 值的 Integer 实例。如果不需要新的 Integer 实例,则通常应优先使用此方法而不是构造函数 Integer(int),因为通过缓存经常请求的值,该方法很可能会产生更好的空间和时间性能。
参数:
i
- 一个 int 值。
返回:
表示i
的 Integer 实例。
自从:
1.5
参见http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/Integer.html#valueOf%28int%29
JDK 5 中已将此变体添加到 Byte、Short、Integer 和 Long(自 JDK 1.4 起,在 Boolean 的微不足道的情况下已经存在)。这些在 Java 中当然都是不可变对象。过去如果需要从 int 获取 Integer 对象,就需要构造一个新的 Integer。但在 JDK 5+ 中,你应该真正使用 valueOf,因为 Integer 现在会缓存介于-128和127之间的整数对象,并且可以向你返回完全相同的 Integer(0) 对象,而不是浪费对象构造一个全新的相同的 Integer 对象。
private static class IntegerCache {
private IntegerCache(){}
static final Integer cache[] = new Integer[-(-128) + 127 + 1];
static {
for(int i = 0; i < cache.length; i++)
cache[i] = new Integer(i - 128);
}
}
public static Integer valueOf(int i) {
final int offset = 128;
if (i >= -128 && i <= 127) { // must cache
return IntegerCache.cache[i + offset];
}
return new Integer(i);
}
参考为什么您应该使用Integer.valueOf(int)
编辑
自动装箱和对象创建:
我们必须考虑的重要点是,自动装箱不会减少对象创建,但可以减少代码复杂性。一个好的经验法则是,在没有对象需要的情况下使用基本类型,有两个原因:
基本类型不会比它们对应的包装类型更慢,而且可能快得多。 存在一些意外行为,涉及==(比较引用)和.equals()(比较值)。
通常,当基本类型装箱到包装类型时,JVM分配内存并创建新对象。但是对于某些特殊情况,JVM将重用同一对象。
以下是存储为不可变对象的原始类型列表:
布尔值true和false
所有字节值
介于-128和127之间的短值
介于-128和127之间的int值
\u0000到\u007F范围内的字符
请参考http://today.java.net/pub/a/today/2005/03/24/autoboxing.html#performance_issue
缓存中只实现了-128到+127之间的范围。
Integer a = new Integer(1);
Integer b = new Integer(1);
System.out.println("a==b? " + (a==b));
Integer c = Integer.valueOf(127);
Integer d = Integer.valueOf(127);
System.out.println("c==d? " + (c==d));
Integer e = Integer.valueOf(128);
Integer f = Integer.valueOf(128);
System.out.println("e==f? " + (e==f));
int是原始类型,不是对象。
new Integer(123)
和Integer.valueOf(123)
都返回表示值为123的Integer
对象。根据Integer.valueOf()
的javadoc:
返回一个表示指定int值的Integer实例。 如果不需要新的Integer实例,则通常应优先使用此方法而不是构造函数Integer(int),因为通过缓存经常请求的值,此方法可能会产生明显更好的空间和时间性能。
你的方法需要一个 int
还是一个 Integer
?
new Integer(int)
和 Integer.valueOf(int)
都返回 Integer
对象,但应该优先使用 valueOf
,因为它更高效,可以返回缓存的对象。如果你的方法需要一个 Integer
,你应该使用 Integer.valueOf
。
如果你的方法需要一个 int
,你应该使用一个 int
(例如:123
)。
然而,严格按照类型匹配并不是必须的,因为由于自动装箱的存在,当类型不匹配时会自动将int
转换为Integer
,反之亦然。这使得您可以将int
传递到需要Integer
的方法中,将Integer
传递到需要int
的方法中。但请注意,自动装箱会带来性能开销。使用自动装箱最常见的示例是如果您想要在集合中存储基本类型。
new Integer(88)
的东西时,SpotBugs 代码分析工具会抱怨性能问题。new
和valueOf
之间的差异。
myMethod(Integer.valueOf(123))
或者myMethod(123)
,实际上并没有区别,因为自动装箱会为你使用Integer.valueOf()
。根据可读性自行判断哪种方式更好。(假设myMethod
接收的是Integer
类型参数) - soulcheck