JDK8源码系列--Integer类区间数据缓存

一、包装类

关注点1:基本类型与包装类

(1)一切皆对象,但是基本类型却不是对象。
(2)声明方式不同,引用数据类型需要用new关键字来创建,基本数据类型不需要。
(3)存储位置不同,基本数据类型直接存储保存在堆栈中,能高效存取,引用数据类型需要引用指向实例,具体的实列保存在堆中。
(4)引用数据类型的初始值为null,基本数据类型的初始值依其数据类型而定。

关注点2:包装类存在的意义

基本数据类型不是对象,不是Object的子类,不能参与面向对象的开发。在设计到面向对象开发时,就会需要包装类。比较典型的场景,例如hashCode()获取哈希值,或者getClass()获取类等。包装类型可以解决基本数据类型解决不了的事情:泛型类型参数、序列化、类型转换、高频区间数据缓存等。

List<Integer> list = new ArrayList<>();
list.add(1);
---------------------------------------
List list = new ArrayList();
list.add(Integer.valueOf(1));

二、Integer源码分析与高速区间数据缓存

1. 类定义

public final class Integer extends Number implements Comparable<Integer>

(1)由final修饰,不能被继承。
(2)实现Comparable接口,可比较,代码中实现compareTo(i)方法。
(3)继承Number类,代码中实现6种数值类型转换方法。Number类实现Serializable接口,表示Integer类可序列化。

2. 属性和常量

常量

@Native public static final int   MIN_VALUE = 0x80000000; // 最小值
@Native public static final int   MAX_VALUE = 0x7fffffff; // 最大值
@Native public static final int SIZE = 32; // int二进制位数
public static final int BYTES = SIZE / Byte.SIZE; // 二进制int字节数,JDK8新增
public static final Class<Integer>  TYPE = (Class<Integer>) Class.getPrimitiveClass("int"); // 标记int包装类

属性

private final int value;

value是Integer中唯一的属性,由final修饰,赋值后不能修改。

3. 常用方法

Integer中方法很多是类型转换方法,例如实现Number类的抽象方法(intValue()等),实现compareTo方法。IntegerhashCode值是int值。

// 返回保存指定值的Integer对象,默认十进制
public static Integer valueOf(String s)
// 返回Integer对象对应int值
public int intValue()
// 以二进制无符号整数形式返回一个整数的字符串表示。
public static String toBinaryString(int i)
// 获取系统属性中指定名称nm对应值,val为默认值。
public static Integer getInteger(String nm, int val)

JDK8新增了几个聚合函数

public static int sum(int a, int b)
public static int max(int a, int b)
public static int min(int a, int b)

4. Integer高速区间缓存

public static Integer valueOf(int i) {
    if (i >= IntegerCache.low && i <= IntegerCache.high)
        return IntegerCache.cache[i + (-IntegerCache.low)];
    return new Integer(i);
}

返回int数值的Integer实例。如果不需要创建新的Integer实例,valueOf()相比于new Integer(i)方法有着更好的空间和时间性能。性能提升是通过缓存常用值实现的。IntegerCache.cache数组中至少缓存[-128,127]范围的Integer实例。

private static class IntegerCache {
    static final int low = -128;
    static final int high;
    static final Integer cache[];

    static {
        // high value may be configured by property
        int h = 127;
        String integerCacheHighPropValue =
            sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
        if (integerCacheHighPropValue != null) {
            try {
                int i = parseInt(integerCacheHighPropValue);
                i = Math.max(i, 127);
                // Maximum array size is Integer.MAX_VALUE
                h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
            } catch( NumberFormatException nfe) {
                // If the property cannot be parsed into an int, ignore it.
            }
        }
        high = h;

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

        // range [-128, 127] must be interned (JLS7 5.1.7)
        assert IntegerCache.high >= 127;
    }

    private IntegerCache() {}
}

IntegerCache是私有的静态内部类,外部类不能引用该类。类中包含三个final属性,分别是缓存实例对应int值范围lowhigh,一个Integer数组cache用来存放实例。IntegerCache缓存在首次使用时初始化。

在8中基本数据类型对应的包装类中,除了浮点类型FloatDouble类型,其余6个包装类都设置了高速区间数据缓存,缓存范围可见《基本数据类型小节》的总结图。比较特殊的是,Integer是唯一可以修改缓存范围的包装类。IntegerCachehigh默认值是127,可以设置JVM参数-XX:AutoBoxCacheMax=<size>。缓存数组cache的最大范围是Integer.MAX_VALUE,size值小于等于Integer.MAX_VALUE - 128 - 1,并且必然大于等于127

对于Integer var = 42,我们知道自动装箱是Java语法糖,实际上底层实现代码时Integer var = Integer.valueOf(42)。使用了valueOf()方法,就用到了IntegerCache缓存。因此,在高速区间数据缓存范围内的值可以通过 == 判断。区间内的值会复用已有对象,区间外的数据会在堆上生成,并不会复用已有的对象。因此,对于包装类的比较,采用equals方法比较好,保持一致性。

Integer a = 42;
Integer b = 42;
System.out.println(a == b); // true
System.out.println(a.equals(b)); // true
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值