【问题标题】:New Integer vs valueOf新整数与 valueOf
【发布时间】:2011-02-27 19:24:29
【问题描述】:

我使用Sonar 使我的代码更清晰,它指出我使用new Integer(1) 而不是Integer.valueOf(1)。因为valueOf 似乎没有实例化新对象,所以对内存更友好。 valueOf 怎么能不实例化一个新对象呢?它是如何工作的?对所有整数都是这样吗?

【问题讨论】:

  • 注意:如果你使用自动装箱,它会为你使用 Integer.valueOf(int)。

标签: java sonarqube


【解决方案1】:

Integer.valueOf 为值-128+127 实现缓存。请参阅 Java 语言规范的最后一段,第 5.1.7 节,其中解释了装箱的要求(通常根据 .valueOf 方法实现)。

http://docs.oracle.com/javase/specs/jls/se7/html/jls-5.html#jls-5.1.7

【讨论】:

  • 我知道,它在拆箱中的某个地方,但我可以找到该部分。谢谢
  • 该部分没有明确说明 valueOf。装箱通常根据 valueOf 实现,但这不是必需的。此外,还允许缓存该范围之外的值。这只是拳击的最低范围。
  • 为了完整起见,还请注意,在 Sun VM 上,缓存的最大值可由用户使用 -XX:AutoBoxCacheMax=... 进行配置
  • @MarkPeters 以获得额外的完整性;-) 该功能仅在最近更新 Sun Java 6 后才可用(我认为更新 14 左右)。
【解决方案2】:

来自 java.lang.Integer 源代码。整数缓存是可配置的。要配置 Sun 以外的整数缓存大小,我们需要根据源代码使用系统属性 java.lang.Integer.IntegerCache.high

/**
 * Cache to support the object identity semantics of autoboxing for values between 
 * -128 and 127 (inclusive) as required by JLS.
 *
 * The cache is initialized on first usage. During VM initialization the
 * getAndRemoveCacheProperties method may be used to get and remove any system
 * properites that configure the cache size. At this time, the size of the
 * cache may be controlled by the vm option -XX:AutoBoxCacheMax=<size>.
 */

// value of java.lang.Integer.IntegerCache.high property (obtained during VM init)
private static String integerCacheHighPropValue;

static void getAndRemoveCacheProperties() {
    if (!sun.misc.VM.isBooted()) {
        Properties props = System.getProperties();
        integerCacheHighPropValue =
            (String)props.remove("java.lang.Integer.IntegerCache.high");
        if (integerCacheHighPropValue != null)
            System.setProperties(props);  // remove from system props
    }
}

private static class IntegerCache {
    static final int high;
    static final Integer cache[];

    static {
        final int low = -128;

        // high value may be configured by property
        int h = 127;
        if (integerCacheHighPropValue != null) {
            // Use Long.decode here to avoid invoking methods that
            // require Integer's autoboxing cache to be initialized
            int i = Long.decode(integerCacheHighPropValue).intValue();
            i = Math.max(i, 127);
            // Maximum array size is Integer.MAX_VALUE
            h = Math.min(i, Integer.MAX_VALUE - -low);
        }
        high = h;

        cache = new Integer[(high - low) + 1];
        int j = low;
        for(int k = 0; k < cache.length; k++)
            cache[k] = new Integer(j++);
    }

    private IntegerCache() {}
}

从 java.lang.Short、java.lang.Byte 和 java.lang.Long 创建一个 127 到 -128 的缓存

private static class LongCache {
    private LongCache() {
    }

    static final Long cache[] = new Long[-(-128) + 127 + 1];

    static {
        for (int i = 0; i < cache.length; i++)
            cache[i] = new Long(i - 128);
    }
}

private static class ShortCache {
    private ShortCache() {
    }

    static final Short cache[] = new Short[-(-128) + 127 + 1];

    static {
        for (int i = 0; i < cache.length; i++)
            cache[i] = new Short((short) (i - 128));
    }
}

private static class ByteCache {
    private ByteCache() {
    }

    static final Byte cache[] = new Byte[-(-128) + 127 + 1];

    static {
        for (int i = 0; i < cache.length; i++)
            cache[i] = new Byte((byte) (i - 128));
    }
}

【讨论】:

    【解决方案3】:

    他们正在推动您使用valueOf() 而不是new Integer(),因此valueOf() 方法会为您执行此操作,并缓存该值以防您将来再次获得相同的数字。在这种情况下,方法不会实例化新整数,但会给你缓存的整数,这将使新整数的“创建”更快且内存友好的过程..

    如果你是没有经验的 Java 程序员,这样你可能会给自己带来很多问题,因为你会得出 Integer.valueOf(342)==Integer.valueOf(342) 的结论,因为你可能(或可能没有)两个整数的指针相同,并且可能你会练习它比方说,你在 C# 中学习过一种方法,因此它会不时向你展示错误,而你将不知道这些错误是如何以及从哪里来的......

    【讨论】:

      【解决方案4】:

      来自JavaDoc

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

      ValueOf 通常用于自动装箱,因此(用于自动装箱时)至少缓存 -128 到 127 之间的值以遵循自动装箱规范。

      这是 Sun JVM 1.5 的 valueOf 实现。?看看整个类,看看缓存是如何初始化的。

      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);
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-01-09
        相关资源
        最近更新 更多