ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

Java包装类缓存

2021-07-14 22:03:26  阅读:203  来源: 互联网

标签:缓存 Java 包装 127 int static new 128 Integer


Java基本类型的包装类的大部分都实现了常量池技术,即Byte,Short,Integer,Long

这四种包装类默认创建了数值[-128,127]的相应类型的缓存数据,Character创建了数值在[0,127]范围的缓存数据,Boolean直接返回true或者false。超出此范围会创建新的对象。

public static Boolean vatue0f(boolean b){
    return(b?TRUE:FALSE);
}
private static class CharacterCache{
    private CharacterCache(){}
    static final Character cache[]=new Character[127+1];
    static{
        for(int i=0;i<cache.Length;i++)
            cache[i]=new Character((char)i);
    }
}

浮点类型的包装类Float和Double没有实现常量池技术

缓存区间设置为[-128,127]的原因:

https://github.com/Snailclimb/JavaGuide/issues/461

由于Integer变量是对一个Integer对象的引用,所以两个通过new生成的Integer变量永远是不相等的(在堆内存地址不同)。

Integer i = new Integer(100);
Integer j = new Integer(100);
System.out.print(i == j); //false

非new生成的Integer变量和new Integer()生成的变量比较时,结果为false。(非new生成的 Integer变量指向的是java常量池中的对象,而new Integer()生成的变量指向堆中新建的对象,两者在内存中的地址不同)

Integer b = new Integer(100);
Integer c=100;
System.out.println(b == c); // false

对于两个非new生成的Integer对象,进行比较时,如果两个变量的值在区间-128到127之间,则为true,如果不在这区间,则为false

Integer i = 100;
Integer j = 100;
System.out.print(i == j); //true
Integer i = 128;
Integer j = 128;
System.out.print(i == j); //false

因为当值在 -128 ~ 127之间时,java会进行自动装箱,然后会对值进行缓存,如果有相同的值,会直接在缓存中取出使用。缓存是通过Integer的内部类IntegerCache来完成的。当值超出此范围,会在堆中 new出一个对象来存储。

给一个Integer对象赋一个int值的时候,会调用Integer类的静态方法valueOf

Integer i=30;在编译的时候会直接将30封装为Integer。

i=Integer.valueOf(30);会使用常量池中的对象。

源码:

public static Integer valueOf(String s, int radix) throws NumberFormatException
{
    return Integer.valueOf(parseInt(s,radix));
}
/**
* (1)在-128~127之内:静态常量池中cache数组是static final类型,该对象会被存储于静
态常量池中。
* cache数组里面的元素不是static final类型,而是cache[k] = new Integer(j++),
* 这些元素是存储于堆中,只是cache数组对象存储的是堆中的Integer对象的地址
*
* (2)在-128~127 之外:在堆中新建一个 Integer对象,并返回。
*/
public static Integer valueOf(int i) {
    assert IntegerCache.high >= 127;
    if (i >= IntegerCache.low && i <= IntegerCache.high) {
        return IntegerCache.cache[i + (-IntegerCache.low)];
    }
    return new Integer(i);
}

IntegerCache是Integer的内部类,源码:

/**
* 缓存支持自动装箱的对象标识语义 -128和127(含)。
* 缓存在第一次使用时初始化。 缓存的大小可以由-XX:AutoBoxCacheMax = <size>选项控制。
* 在VM初始化期间,java.lang.Integer.IntegerCache.high属性可以设置并保存在私有系统
属性中
*/
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) {
        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);
    }
    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() {}
}

最大边界可以通过-XX:AutoBoxCacheMax进行配置

Integer a=newInteger(48);
Integer b=newInteger(48);
Integer c=newInteger(0);
System.out.println("a=b+c"+(a==b+c));

由于+不适用于Integer对象,所以b,c会先自动拆箱进行数值相加,又由于Integer对象无法与数值直接比较,所以a自动拆箱为int,最终转为48==48 

标签:缓存,Java,包装,127,int,static,new,128,Integer
来源: https://blog.csdn.net/weixin_47183168/article/details/118737244

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有