前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >JDK源码分析 Integer

JDK源码分析 Integer

作者头像
Yano_nankai
发布2018-10-08 10:41:15
2660
发布2018-10-08 10:41:15
举报
文章被收录于专栏:二进制文集二进制文集

说明

对于JDK源码分析的文章,仅仅记录我认为重要的地方。源码的细节实在太多,不可能面面俱到地写清每个逻辑。所以我的JDK源码分析,着重在JDK的体系架构层面,具体源码可以参考:http://www.cnblogs.com/skywang12345/category/455711.html

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 继承结构

源码中可学习的地方

最大值、最小值

代码语言:javascript
复制
/**
 * A constant holding the minimum value an <code>int</code> can
 * have, -2<sup>31</sup>.
 */
public static final int   MIN_VALUE = 0x80000000;
/**
 * A constant holding the maximum value an <code>int</code> can
 * have, 2<sup>31</sup>-1.
 */
public static final int   MAX_VALUE = 0x7fffffff;

高效率计算 q * 100

代码语言:javascript
复制
(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的幂

代码语言:javascript
复制
if( (n & -n) == n)

测试用例:

代码语言:javascript
复制
@Test
public void testInteger() {
    System.out.println(Integer.toBinaryString(4));
    System.out.println(Integer.toBinaryString(-4));
    System.out.println(4 & (-4));
}

结果

代码语言:javascript
复制
100
11111111111111111111111111111100
4

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

代码语言:javascript
复制
if( n & (n - 1) == 0)

Integer 的缓存(坑)

先看下面的示例:

代码语言:javascript
复制
@Test
public void testInteger() {
    Integer i1 = 127, i2 = 127;
    System.out.println("127 i1 == i2: " + (i1 == i2));
    i1 = 128; i2 = 128;
    System.out.println("128 i1 == i2: " + (i1 == i2));
    System.out.println("128 equals: " + i1.equals(i2));
}

输出的结果是:

代码语言:javascript
复制
127 i1 == i2: true
128 i1 == i2: false
128 equals: true

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

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

对应的源码为:

代码语言:javascript
复制
public static Integer valueOf(int i) {
    if(i >= -128 && i <= IntegerCache.high)
        return IntegerCache.cache[i + 128];
    else
        return new Integer(i);
}

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

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

代码语言:javascript
复制
 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.
代码语言:javascript
复制
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() {}
}

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

代码语言:javascript
复制
/**
 * 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
    }
}
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2017.08.06 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 说明
  • Integer 说明
    • Number 接口
    • Integer 继承结构
    • 源码中可学习的地方
      • 最大值、最小值
        • 高效率计算 q * 100
          • 高效率判断 一个数是否是2的幂
            • Integer 的缓存(坑)
              • 为什么对于Integer是127的对象,用==竟然是相同的对象呢?
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档