[关闭]
@Yano 2017-08-06T19:31:21.000000Z 字数 3486 阅读 2124

JDK源码分析 Integer

Java


说明

对于JDK源码分析的文章,仅仅记录我认为重要的地方。源码的细节实在太多,不可能面面俱到地写清每个逻辑。所以我的JDK源码分析,着重在JDK的体系架构层面,具体源码可以参考:博客园:如果天空不死-博客

Integer 说明

The Integer class wraps a value of the primitive type int in an object. An object of type Integer contains a single field whose type is int.

In addition, this class provides several methods for converting an int to a String and a String to an int, as well as other constants and methods useful when dealing with an int.

Number 接口

其继承了Number接口,能够转换成 int, long, float, double, byte, short等类型。

继承了Number接口的类,还有:AtomicInteger, AtomicLong, BigDecimal, BigInteger, Byte, Double, DoubleAccumulator, DoubleAdder, Float, Integer, Long, LongAccumulator, LongAdder, Short。

Integer 继承结构

源码中可学习的地方

最大值、最小值

  1. /**
  2. * A constant holding the minimum value an <code>int</code> can
  3. * have, -2<sup>31</sup>.
  4. */
  5. public static final int MIN_VALUE = 0x80000000;
  6. /**
  7. * A constant holding the maximum value an <code>int</code> can
  8. * have, 2<sup>31</sup>-1.
  9. */
  10. public static final int MAX_VALUE = 0x7fffffff;

高效率计算 q * 100

  1. (q << 6) + (q << 5) + (q << 2)

分析:
- q << n,表示q乘以2^n
- q >> n,表示q除以2^n

2^6 + 2^5 + 2^2 = 64 + 32 + 4 = 100

高效率判断 一个数是否是2的幂

  1. if( (n & -n) == n)

测试用例:

  1. @Test
  2. public void testInteger() {
  3. System.out.println(Integer.toBinaryString(4));
  4. System.out.println(Integer.toBinaryString(-4));
  5. System.out.println(4 & (-4));
  6. }

结果

100
11111111111111111111111111111100
4

其实还可以用如下判断,因为2的幂,只有一位是1,其余位全是0;如果-1的话,就变成原来位为1位置的后置位全为1。例如8为1000,8-1=7为0111

  1. if( n & (n - 1) == 0)

Integer 的缓存(坑)

先看下面的示例:

  1. @Test
  2. public void testInteger() {
  3. Integer i1 = 127, i2 = 127;
  4. System.out.println("127 i1 == i2: " + (i1 == i2));
  5. i1 = 128; i2 = 128;
  6. System.out.println("128 i1 == i2: " + (i1 == i2));
  7. System.out.println("128 equals: " + i1.equals(i2));
  8. }

输出的结果是:

127 i1 == i2: true
128 i1 == i2: false
128 equals: true

为什么对于Integer是127的对象,用==竟然是相同的对象呢?

这是因为Integer类内部,对值为-128~127的对象,进行了缓存~!这些对象是在JVM加载Integer时就创建好的。

对应的源码为:

  1. public static Integer valueOf(int i) {
  2. if(i >= -128 && i <= IntegerCache.high)
  3. return IntegerCache.cache[i + 128];
  4. else
  5. return new Integer(i);
  6. }

我们可以看到,如果i在-128和IntegerCache.high之间,会返回IntegerCache.cache[i + 128]。类IntegerCache已经缓存了值为-128和IntegerCache.high的Integer对象。

注释中解释了为什么要这么设计(为了节省时间和空间,-128~127可能是最常用的):

 If a new Integer instance is not required, this method should generally be used in preference to the constructor Integer(int), as this method is likely to yield significantly better space and time performance by caching frequently requested values.
  1. private static class IntegerCache {
  2. static final int high;
  3. static final Integer cache[];
  4. static {
  5. final int low = -128;
  6. // high value may be configured by property
  7. int h = 127;
  8. if (integerCacheHighPropValue != null) {
  9. // Use Long.decode here to avoid invoking methods that
  10. // require Integer's autoboxing cache to be initialized
  11. int i = Long.decode(integerCacheHighPropValue).intValue();
  12. i = Math.max(i, 127);
  13. // Maximum array size is Integer.MAX_VALUE
  14. h = Math.min(i, Integer.MAX_VALUE - -low);
  15. }
  16. high = h;
  17. cache = new Integer[(high - low) + 1];
  18. int j = low;
  19. for(int k = 0; k < cache.length; k++)
  20. cache[k] = new Integer(j++);
  21. }
  22. private IntegerCache() {}
  23. }

h 默认是 127,但是可以通过 vm 参数指定:-XX:AutoBoxCacheMax。

  1. /**
  2. * Cache to support the object identity semantics of autoboxing for values between
  3. * -128 and 127 (inclusive) as required by JLS.
  4. *
  5. * The cache is initialized on first usage. During VM initialization the
  6. * getAndRemoveCacheProperties method may be used to get and remove any system
  7. * properites that configure the cache size. At this time, the size of the
  8. * cache may be controlled by the vm option -XX:AutoBoxCacheMax=<size>.
  9. */
  10. // value of java.lang.Integer.IntegerCache.high property (obtained during VM init)
  11. private static String integerCacheHighPropValue;
  12. static void getAndRemoveCacheProperties() {
  13. if (!sun.misc.VM.isBooted()) {
  14. Properties props = System.getProperties();
  15. integerCacheHighPropValue =
  16. (String)props.remove("java.lang.Integer.IntegerCache.high");
  17. if (integerCacheHighPropValue != null)
  18. System.setProperties(props); // remove from system props
  19. }
  20. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注