欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Integer缓存机制-基本数据类型和包装类型-自动拆装箱

程序员文章站 2022-04-15 11:12:49
Integer缓存机制 总结: 1、jdk1.5对Integer新增了缓存机制,范围在-128-127(这个范围的整数值使用频率最高)内的自动装箱返回的是缓存对象,不会new新的对象,所以只要在缓存范围内值相等自动装箱返回的对象一样。jdk1.6后缓存范围的最大值127可以通过设置jvm的启动参数( ......

integer缓存机制

总结:

1、jdk1.5对integer新增了缓存机制,范围在-128-127(这个范围的整数值使用频率最高)内的自动装箱返回的是缓存对象,不会new新的对象,所以只要在缓存范围内值相等自动装箱返回的对象一样。jdk1.6后缓存范围的最大值127可以通过设置jvm的启动参数(-xx:autoboxcachemax=size)调整
2、integer的缓存只在自动装箱时有效,使用构造器(new)创建的对象不会触发缓存
3、int和integer比较时不用考虑缓存问题,因为integer会自动拆箱为int再和int比较,这时只是单纯的比较值是否相等

详解:
针对integer常见的一个面试题为

integer i1 = 100;
integer i2 = 100;
integer j1 = 200;
integer j2 = 200;
system.out.println(i1 == i2); // 输出 true
system.out.println(j1 == j2); // 输出 false

我们对于integer最基本的理解是integer是int的包装类,是引用数据类型,引用数据类型用==比较的是对象的内存地址。
我们来看i1的创建过程(jdk1.8)
首先会对integer i1 = 100;自动装箱(其实就是调用valueof方法),java会把这段编译为integer i1 = integer.valueof(100),可以自行查看class文件验证。
然后再看integer.valueof方法:

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

 

可以清楚的看到是先从integercache取值,integercache.low integercache.high 范围外则直接new对象(new的对象会存在堆内存中)

我们再来看integercache类,integercache为integer的私有静态类

 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.  the size of the cache 第一次使用时生效
 6      * may be controlled by the {@code -xx:autoboxcachemax=<size>} option. 可通过参数设置最大值
 7      * during vm initialization, java.lang.integer.integercache.high property
 8      * may be set and saved in the private system properties in the
 9      * sun.misc.vm class.
10      */
11 
12     private static class integercache {
13         static final int low = -128;
14         static final int high;
15         static final integer cache[];
16 
17         static {
18             // high value may be configured by property
19             int h = 127;
20             string integercachehighpropvalue =
21                 sun.misc.vm.getsavedproperty("java.lang.integer.integercache.high");
22             if (integercachehighpropvalue != null) {
23                 try {
24                     int i = parseint(integercachehighpropvalue);
25                     i = math.max(i, 127);
26                     // maximum array size is integer.max_value
27                     h = math.min(i, integer.max_value - (-low) -1);
28                 } catch( numberformatexception nfe) {
29                     // if the property cannot be parsed into an int, ignore it.
30                 }
31             }
32             high = h;
33 
34             cache = new integer[(high - low) + 1];
35             int j = low;
36             for(int k = 0; k < cache.length; k++)
37                 cache[k] = new integer(j++);
38 
39             // range [-128, 127] must be interned (jls7 5.1.7)
40             assert integercache.high >= 127;
41         }
42 
43         private integercache() {}
44     }

 

integer的缓存通过for循环创建存放到一个数组中,注释已经解释该数组会在integer第一次使用时初始化,结合类加载顺序来理解,第一次使用integer时内部静态类会被初始化,静态代码块会被执行,存到堆中。会有第一次惩罚

jdk1.5源码参考

 1 private static class integercache {
 2         static final integer[] cache = new integer[256];
 3 
 4         static {
 5             for (int i = 0; i < cache.length; i++) {
 6                 cache[i] = new integer(i - 128);
 7             }
 8         }
 9     }
10 
11     public static integer valueof(int paramint) {
12         if ((paramint >= -128) && (paramint <= 127)) {
13             return integercache.cache[(paramint + 128)];
14         }
15         return new integer(paramint);
16     }

integer与int用==比较时integer会自动拆箱(调用intvalue()方法)为int进行比较
i1 == 100 会编译成 i1.intvalue() == 100


其他缓存的对象
这种缓存行为不仅适用于integer对象。我们针对所有整数类型的类都有类似的缓存机制。
有 bytecache 用于缓存 byte 对象
有 shortcache 用于缓存 short 对象
有 longcache 用于缓存 long 对象
有 charactercache 用于缓存 character 对象
byte,short,long 有固定范围: -128 到 127。对于 character, 范围是 0 到 127。除了 integer 可以通过参数改变范围外,其它的都不行。

参考博文:https://blog.csdn.net/qq_27093465/article/details/52473649

 

int与integer(基本类型与包装类型)

integer是int的包装类型,两者的区别为:

1、int初始值为0,integer初始值为null,所有的引用类型都为null;

2、integer为引用类型,对象存放在堆中。int为基本数据类型,对象存放在栈中;

使用包装类的好处:

1、integer封装了很多处理方法,方便操作,比如进制转化(tobinarystring)、数据类型之间的转化(tostring);

2、解决有些类型不支持基础数据类型的情况,比如list只能接收引用类型;

至于何时使用基本数据类型,何时使用包装类型这个就要看具体需求,当只是作为数值不需要更多的操作时用基本类型就可,灵活使用

基本数据类型和对应的包装类
int——integer
float——float 
double——double 
byte——byte
long——long
char——character
boolean——boolean
short——short

 

自动拆装箱(jdk1.5引入)

自动拆箱实际上就是引用类型自动转化成基本数据类型,自动装箱实际上就是基本数据类型自动转化成对应的引用类型

比如创建integer i = new integer(100); 可以直接写成integer i = 100;不需要强转  (自动装箱)

int j = i  基本数据类型j可以直接等于引用类型i  (自动拆箱)

1 integer i = 1;
2 int j = i;
3 
4 /**
5 *    上面代码编译成class后
6 */
7 integer i = integer.valueof(1);
8 int j = i.intvalue();    

由上可以看出自动装箱实际上就是调用了valueof方法,自动拆箱调用了intvalue方法