美文网首页直面Java系列
包装类的意义与高速区间数据缓存

包装类的意义与高速区间数据缓存

作者: Awecoder | 来源:发表于2019-08-25 15:22 被阅读0次

一、包装类

关注点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

相关文章

  • 包装类的意义与高速区间数据缓存

    一、包装类 关注点1:基本类型与包装类 (1)一切皆对象,但是基本类型却不是对象。(2)声明方式不同,引用数据类型...

  • Integer包装类转换

    intvalue把包装类转成基本数据类型, parseInt包字符串转成对应的包装类 valueOf(高速缓存)

  • Java基本数据类型

    简单类型二进制位数取值范围默认值包装类高频区间数据缓存范围byte8-2^8 - 2^8-10Byte-128 -...

  • CPU多级缓存

    左图为最简单的高速缓存的配置,数据的读取和存储都经过高速缓存,CPU核心与高速缓存有一条特殊的快速通道;主存与高速...

  • 慕课网高并发实战(一)-JAVA并发基础

    .课程网站 CPU多级缓存 左图为最简单的高速缓存的配置,数据的读取和存储都经过高速缓存,CPU核心与高速缓存有一...

  • 慕课网高并发实战(二)-并发基础

    课程网址 1.CPU多级缓存 左图为最简单的高速缓存的配置,数据的读取和存储都经过高速缓存,CPU核心与高速缓存有...

  • 高并发基础一

    最简单的高速缓存的配置,数据的读取和存储都经过高速缓存,CPU核心与高速缓存有一条特殊的快速通道;主存和高速缓存都...

  • Java高并发编程学习笔记(二)-并发基础

    1.CPU多级缓存 左图为最简单的高速缓存的配置,数据的读取和存储都经过高速缓存,CPU核心与高速缓存有一条特殊的...

  • 慕课网高并发实战(二)-并发基础

    1.CPU多级缓存 左图为最简单的高速缓存的配置,数据的读取和存储都经过高速缓存,CPU核心与高速缓存有一条特殊的...

  • CPU多级缓存

    下图为最简单的高速缓存的配置,数据的读取和存储都经过高速缓存,CPU核心与高速缓存有一条特殊的快速通道;主存和高速...

网友评论

    本文标题:包装类的意义与高速区间数据缓存

    本文链接:https://www.haomeiwen.com/subject/rkohectx.html