Integer的缓存和自动拆装箱
先看一个简单的例子:
public class TestInteger {
public static void main(String[] args) {
System.out.println("----20----");
littleNum();
System.out.println();
System.out.println("----250----");
bigNum();
}
public static void littleNum(){
Integer i1 = 20; //1
Integer i2 = 20; //2
Integer i3 = new Integer(20); //3
Integer i4 = new Integer(20); //4
int i5 = 20; //5
System.out.println("i1==i2?: " + (i1 == i2));
System.out.println("i1==i3?: " + (i1 == i3));
System.out.println("i1==i5?: " + (i1 == i5));
System.out.println("i3==i4?: " + (i3 == i4));
System.out.println("i3==i5?: " + (i3 == i5));
}
public static void bigNum(){
Integer i1 = 250; //1
Integer i2 = 250; //2
Integer i3 = new Integer(250); //3
Integer i4 = new Integer(250); //4
int i5 = 250; //5
System.out.println("i1==i2?: " + (i1 == i2));
System.out.println("i1==i3?: " + (i1 == i3));
System.out.println("i1==i5?: " + (i1 == i5));
System.out.println("i3==i4?: " + (i3 == i4));
System.out.println("i3==i5?: " + (i3 == i5));
}
}
打印结果是:
----20----
i1==i2?: true
i1==i3?: false
i1==i5?: true
i3==i4?: false
i3==i5?: true
----250----
i1==i2?: false
i1==i3?: false
i1==i5?: true
i3==i4?: false
i3==i5?: true
结果好像跟想象中的不太一样,这里涉及到自动拆装箱的问题。
自动装箱和拆箱从Java 1.5开始引入,自动装箱与拆箱的机制可以让我们在Java的变量赋值或者是方法调用等情况下使用原始类型或者对象类型更加简单直接。
自动装箱就是Java自动将基本类型值转换成对应包装类的对象,比如将int的变量转换成Integer对象,这个过程叫做装箱,反之将Integer对象转换成int类型值,这个过程叫做拆箱。
这里的拆装箱是由编译器自动完成的,所以就称作为自动装箱和拆箱。
基本类型包括byte,short,char,int,long,float,double和boolean对应的封装类为Byte,Short,Character,Integer,Long,Float,Double,Boolean。
自动装箱时编译器调用valueOf()将基本类型值转换成对象,同时自动拆箱时,编译器通过调用类似intValue(),doubleValue()这类的方法将对象转换成节本类型值。
我们都知道对于 == 而言,在比较基本数据类型的时候是比较的它们的值,而在比较引用数据类型的时候是比较它们的内存地址。
所以,对于 i1==i3?: false 以及 i3==i4?: false 而言,后者是通过new产生的一个新对象,内存地址不同,结果为false;
而对于i1==i5?: true以及i3==i5?: true而言,i5是基本数据类型,==比较的是它们的值,所以结果都是true;
说到 == 的比较,这里要补充一下,Integer类里面重写了equals()方法,所以equals()方法比较的是值
说完了 == 的比较,下面来说一下i1==i2 为什么对于20和对250的结果不一样。
这里就牵涉到Integer的缓存,在 Java 5 中,为 Integer 的操作引入了一个新的特性,用来节省内存和提高性能。整型对象在内部实现中通过使用相同的对象引用实现了缓存和重用。
在Integer的源码中,有一个IntegerCache的内部类,实现了Integer的缓存:
/**
* 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 -XX:AutoBoxCacheMax=<size> option.
*/
// 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
}
}
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;
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));
}
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() {}
}
这里可以看到,一般而言对于 -128-127之间的Integer类型,IntegerCache内部使用了一个Integer的数组来保存它们,而在Integer的valueOf()方法中,调用了IntegerCache的这个缓存池。
valueOf()的源代码如下:
/**
* Returns an {@code Integer} instance representing the specified
* {@code int} value. If a new {@code Integer} instance is not
* required, this method should generally be used in preference to
* the constructor {@link #Integer(int)}, as this method is likely
* to yield significantly better space and time performance by
* caching frequently requested values.
*
* @param i an {@code int} value.
* @return an {@code Integer} instance representing {@code i}.
* @since 1.5
*/
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);
}
回到之前的问题上来,在-128-127之间的Integer类型直接从缓存里面取,而在这之外的Integer类型会通过new创建一个新的对象。
这种 Integer 缓存策略仅在自动装箱的时候有用,使用构造器创建的 Integer 对象不能被缓存。因为在自动装箱过程中会调用Integer的valueOf()方法。
回头细看一下IntegerCache这个类的javadoc,Javadoc 详细的说明这个类是用来实现缓存支持,并支持 -128 到 127 之间的自动装箱过程。最大值 127 可以通过 JVM 的启动参数 -XX:AutoBoxCacheMax=size 修改。
这个缓存会在 Integer 类第一次被使用的时候被初始化出来。以后,就可以使用缓存中包含的实例对象,而不是创建一个新的实例(在自动装箱的情况下)。
实际上在 Java 5 中引入这个特性的时候,范围是固定的 -128 至 +127。后来在 Java 6 中,最大值映射到 java.lang.Integer.IntegerCache.high,可以使用 JVM 的启动参数设置最大值。
除了Integer之外,其他的一些包装类型也存在类似的缓存机制,比如Short型:
private static class ShortCache {
private ShortCache(){}
static final Short cache[] = new Short[-(-128) + 127 + 1];
static {
for(int i = 0; i < cache.length; i++)
cache[i] = new Short((short)(i - 128));
}
}
和Integer不同的是,Short的范围是固定在-128-127不变的。
Byte,Short,Long 有固定范围: -128 到 127。对于 Character, 范围是 0 到 127。除了 Integer 可以通过参数改变范围外,其它的都不行。
Integer的缓存和自动拆装箱的更多相关文章
- Java的自动拆装箱与Integer的缓存机制
转载请注明原文地址:https://www.cnblogs.com/ygj0930/p/10832303.html 一:基本类型与包装类型 我们知道,Java有8大基本数据类型,4整2浮1符1 ...
- Integer缓存机制-基本数据类型和包装类型-自动拆装箱
Integer缓存机制 总结: 1.jdk1.5对Integer新增了缓存机制,范围在-128-127(这个范围的整数值使用频率最高)内的自动装箱返回的是缓存对象,不会new新的对象,所以只要在缓存范 ...
- 自动拆装箱(int,Integer)
包装类型Java语言是一个面向对象的语言,但是Java中的基本数据类型却是不面向对象的,这在实际使用时存在很多的不便,为了解决这个不足,在设计类时为每个基本数据类型设计了一个对应的类进行代表,这样八个 ...
- java中的自动拆装箱与缓存(Java核心技术阅读笔记)
最近在读<深入理解java核心技术>,对于里面比较重要的知识点做一个记录! 众所周知,Java是一个面向对象的语言,而java中的基本数据类型却不是面向对象的!为了解决这个问题,Java为 ...
- 《java入门第一季》之Integer类和自动拆装箱概述
/ * int 仅仅是一个基本类型.int有对应的类类型,那就是Integer. * 为了对基本数据类型进行更多的操作,更方便的操作,Java就针对每一种基本数据类型提供了对应的类类型--包装类类型 ...
- 关于java的自动拆装箱若干细节问题
一.首先需要了解的几个前提: 1.自动装箱过程是通过调用valueOf方法实现的(如Integer.valueOf(10)),而拆箱过程是通过调用包装器的 xxxValue方法实现的(如Integer ...
- Java的自动拆/装箱
作者:Alvin 关键字:语法糖 类 对象 参考 Java 中的语法糖 语法糖--这一篇全了解 浅谈 Integer 类 什么是Java中的自动拆装箱 深入剖析Java中的装箱和拆箱 前言 我们知道, ...
- 一文读懂什么是Java中的自动拆装箱
基本数据类型 基本类型,或者叫做内置类型,是Java中不同于类(Class)的特殊类型.它们是我们编程中使用最频繁的类型. Java是一种强类型语言,第一次申明变量必须说明数据类型,第一次变量赋值称为 ...
- Java基础(二) 基本类型数据类型、包装类及自动拆装箱
我们知道基本数据类型包括byte, short, int, long, float, double, char, boolean,对应的包装类分别是Byte, Short, Integer, Long ...
随机推荐
- bzoj 2186 [Sdoi2008]沙拉公主的困惑(欧拉函数,逆元)
[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=2186 [题意] 若干个询问,求1..n!中与m!互质的个数. [思路] 首先有gcd( ...
- [Hive - LanguageManual] Statistics in Hive
Statistics in Hive Statistics in Hive Motivation Scope Table and Partition Statistics Column Statist ...
- data audit on hadoop fs
最近项目中遇到了存储在HDFS上的数据格式不对,是由于数据中带有\r\n的字符,程序处理的时候没有考虑到这些情况.历史数据大概有一年的时间,需要把错误的数据或者重复的数据给删除了,保留正确的数据,项目 ...
- 【现代程序设计】【homework-07】
C++11 中值得关注的几大变化 1.Lambda 表达式 Lambda表达式来源于函数式编程,说白就了就是在使用的地方定义函数,有的语言叫“闭包”,如果 lambda 函数没有传回值(例如 void ...
- DelphiXE Android自适应屏幕办法
相关资料: http://www.delphitop.com/html/FireMonkey/2658.html http://bbs.csdn.net/topics/390919460 1.Scal ...
- [iOS微博项目 - 2.1] - 获得新浪授权接口
A.如何获得新浪的授权接口 登陆新浪的开放平台 注册新浪账号 创建应用 获得应用id和请求地址 查阅相关API 关联需要进行测试的账号 1.登陆开放平台 http://open.weibo.com ...
- JS一定要放在Body的最底部么? 聊聊浏览器的渲染机制
请参看文章 https://segmentfault.com/a/1190000004292479 网上的回答: 1.js加载会阻塞其它内容加载,使页面加载时间更长,尤其是js文件太大,有的页面js文 ...
- MySQL select into outfile用法
select into outfile用法 SELECT ... FROM TABLE_A INTO OUTFILE "/path/to/file" FIELDS TERMINAT ...
- TypeScript学习笔记(一):介绍及环境搭建
官网 TypeScript目前还在快速的发展中,当前的版本是1.6,有关TypeScript更多的信息可以在其官网中获取. http://www.typescriptlang.org/ 什么是Type ...
- animate平滑回到顶部
Js: //回到顶部 $(".totop").click(function () { $("body,html").animate({scrollTop: 0} ...