33

最近我看到了这样的代码(Java):

myMethod(new Integer(123));

我目前正在重构一些代码,Sonar 工具中有一个提示,使用这样的东西对内存更友好:

myMethod(Integer.valueOf(123));

但是在这种情况下,我认为如果我会使用没有区别:

myMethod(123);

我可以理解,如果我将变量传递给方法,但硬编码 int?或者如果会有 Long/Double 等,我想要 Long 表示数字。但是整数?

4

5 回答 5

40

new Integer(123)将为每个调用创建一个新Object实例。

根据javadoc,它缓存对象有区别......所以如果你不止一次调用它Integer.valueOf(123),你可能(或可能不会)最终得到相同的结果。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值,您使用的是原始类型(考虑到您的方法也在其签名上使用原始类型) - 它会使用更少的内存并且可能更快,但您不会将其添加到集合中,例如。

如果您的方法的签名使用,还请查看 Java 的AutoBoxingInteger - 使用它时,JVM 会自动Integer.valueOf()为您调用(因此也使用缓存)。

于 2012-01-27T08:52:33.593 回答
9

public static Integer valueOf(int i)

返回一个表示指定 int 值的 Integer 实例。如果不需要新的 Integer 实例,则通常应优先使用此方法而不是构造函数 Integer(int),因为此方法可能会通过缓存频繁请求的值来显着提高空间和时间性能。

参数:
i- 一个 int 值。
返回:
a表示 的整数实例i
自:
1.5

参考http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/Integer.html#valueOf%28int%29

valueOf 的这种变体在 JDK 5 中被添加到 Byte、Short、Integer 和 Long(自 JDK 1.4 以来它已经存在于 Boolean 的普通情况中)。当然,所有这些都是 Java 中的不可变对象。过去,如果您需要来自 int 的 Integer 对象,您将构造一个新的 Integer。但是在 JDK 5+ 中,您应该真正使用 valueOf,因为 Integer 现在缓存 -128 和 127 之间的 Integer 对象,并且每次都可以将相同的 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 之间的短值

  • int 值介于 -128 和 127 之间

  • 字符在 \u0000 到 \u007F 范围内

参考http://today.java.net/pub/a/today/2005/03/24/autoboxing.html#performance_issue

于 2012-01-27T08:54:15.260 回答
1

int 是原始类型,而不是对象。

new Integer(123)并且Integer.valueOf(123)都返回Integer表示值 123 的对象。根据 javadoc Integer.valueOf()

返回一个表示指定 int 值的 Integer 实例。如果不需要新的 Integer 实例,则通常应优先使用此方法而不是构造函数 Integer(int),因为此方法可能会通过缓存频繁请求的值来显着提高空间和时间性能。

于 2012-01-27T08:56:03.360 回答
1

你的方法需要一个int还是一个Integer

new Integer(int)并且Integer.valueOf(int)都返回Integer对象,但valueOf应该是首选,因为它更有效,因为它返回缓存的对象。如果您的方法需要Integer您应该使用Integer.valueOf.

如果你的方法需要一个int,你应该使用一个int(例如123)。

但是,由于autoboxing并不一定要以这种方式匹配类型,当类型不匹配时,它会自动将 an 转换int为 an Integer,反之亦然。这允许您将 an 传递int给需要 的方法Integer,并将 an传递给需要Integer的方法int。但请注意,自动装箱会带来性能成本。使用自动装箱的最常见示例是,如果您想将基元存储在集合中。

于 2012-01-27T09:08:50.423 回答
1

仅在 -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)); 

参考这个java规范:

http://java.sun.com/docs/books/jls/third_edition/html/conversions.html#5.1.7

在 JDK 5+ 中,您应该真正使用 valueOf,因为 Integer 现在缓存 -128 和 127 之间的 Integer 对象,并且每次都可以将相同的 Integer(0) 对象交还给您,而不是将对象构造浪费在全新的相同 Integer 对象上。

于 2012-01-27T09:18:35.983 回答