Java 自动装箱和拆箱那些事
2014-12-12 11:52
260 查看
1.JAVA的基本数据类型
在Java中,数据类型可以分为两大种,Primitive Type(基本类型)和Reference Type(引用类型)。基本类型的数值不是对象,不能调用对象的toString()、hashCode()、getClass()、equals()等方法。所以Java提供了针对每种基本类型的包装类型。如下:INDEX | 基本类型 | 大小 | 数值范围 | 默认值 | 包装类型 |
1 | boolean | --- | true,false | false | Boolean |
2 | byte | 8bit | -2^7 -- 2^7-1 | 0 | Byte |
3 | char | 16bit | \u0000 - \uffff | \u0000 | Character |
4 | short | 16bit | -2^15 -- 2^15-1 | 0 | Short |
5 | int | 32bit | -2^31 -- 2^31-1 | 0 | Integer |
6 | long | 64bit | -2^63 -- 2^63-1 | 0 | Long |
7 | float | 32bit | IEEE 754 | 0.0f | Float |
8 | double | 64bit | IEEE 754 | 0.0d | Double |
2.浅谈拆箱与装箱
装箱是将一个原始数据类型赋值给相应封装类的变量。而拆箱则是将一个封装类的变量赋值给相应原始数据类型的变量。Java 1.5中引入了自动装箱和拆箱机制:
(1)自动装箱:把基本类型用它们对应的引用类型包装起来,使它们具有对象的特质,可以调用toString()、hashCode()、getClass()、equals()等方法。
如下:
Integer a=3;//这是自动装箱
其实编译器调用的是static Integer valueOf(int i)这个方法,valueOf(int i)返回一个表示指定int值的Integer对象,那么就变成这样:
Integer a=3; => Integer a=Integer.valueOf(3);
public static Integer valueOf(inti) { if(i >= -128 &&i <=IntegerCache.high) //如果i在-128~high之间,就直接在缓存中取出i的Integer类型对象 return IntegerCache.cache[i + 128]; else return new Integer(i); //否则就在堆内存中创建 }
(2)拆箱:跟自动装箱的方向相反,将Integer及Double这样的引用类型的对象重新简化为基本类型的数据。
如下:
int i = new Integer(2);//这是拆箱
编译器内部会调用int intValue()返回该Integer对象的int值
public int intValue() { return value; }
注意:自动装箱和拆箱是由编译器来完成的,编译器会在编译期根据语法决定是否进行装箱和拆箱动作。
java定义:在自动装箱时对于值从–128到127之间的值,它们被装箱为Integer对象后,会存在内存中被重用,始终只存在一个对象
而如果超过了从–128到127之间的值,被装箱后的Integer对象并不会被重用,即相当于每次装箱时都新建一个 Integer对象;
Integer i1=100;
Integer i2=100;
Integer i3=300;
Integer i4=300;
System.out.println(i1==i2);
System.out.println(i3==i4);
运行结果为“System.out.println(i1==i2);”为 true,但是“System.out.println(i3==i4);”为false。也就意味着,i1与i2这两个Integer类型的引用指向了同一个对象,而i3与i4指向了不同的对象。为什么呢?不都是调用Integer.valueOf(int i)方法吗?
public static Integer valueOf(inti) { if(i >= -128 &&i <=IntegerCache.high) //如果i在-128~high之间,就直接在缓存中取出i的Integer类型对象 return IntegerCache.cache[i + 128]; else return new Integer(i); //否则就在堆内存中创建 }
我们可以看到当i>=-128且i<=IntegerCache.high时,直接返回IntegerCache.cache[i + 128]。其中,IntegerCache为Integer的内部静态类,其原码如下:
private static class IntegerCache {//内部类,注意它的属性都是定义为static final static final inthigh; //缓存上界 static final Integer cache[];//cache缓存是一个存放Integer类型的数组 static {//静态语句块 final int low = -128;//缓存下界,值不可变 // high value may beconfigured by property int h = 127;// h值,可以通过设置jdk的AutoBoxCacheMax参数调整(参见(3)) if (integerCacheHighPropValue !=null) { // Use Long.decode here to avoid invoking methods that // require Integer's autoboxing cache to be initialized // 通过解码integerCacheHighPropValue,而得到一个候选的上界值 int i = Long.decode(integerCacheHighPropValue).intValue(); // 取较大的作为上界,但又不能大于Integer的边界MAX_VALUE i = Math.max(i, 127);//上界最小为127 // Maximum array size is Integer.MAX_VALUE h = Math.min(i, Integer.MAX_VALUE - -low); } high = h; //上界确定,此时high默认一般是127 // 创建缓存块,注意缓存数组大小 cache =new Integer[(high - low) + 1]; int j = low; for(int k = 0; k <cache.length; k++) cache[k] =new Integer(j++);// -128到high值逐一分配到缓存数组 } private IntegerCache() {}//构造方法,不需要构造什么 }
我们可以清楚地看到,IntegerCache有静态成员变量cache,为一个拥有256个元素的数组。在IntegerCache中也对cache进行了初始化,即第i个元素是值为i-128的Integer对象。而-128至127是最常用的Integer对象,这样的做法也在很大程度上提高了性能。也正因为如此,“Integeri1=100;Integer i2=100;”,i1与i2得到是相同的对象。
对比扩展中的第二个实验,我们得知,当封装类与基础类型进行==运行时,封装类会进行拆箱,拆箱结果与基础类型对比值;而两个封装类进行==运行时,与其它的对象进行==运行一样,对比两个对象的地址,也即判断是否两个引用是否指向同一个对象。
扩展:
getAndRemoveCacheProperties方法,用于获取或移除JDK对Integer设置的缓存属性,同时可以通过调整虚拟机-XX:AutoBoxCacheMax=<size>选项,调整“自动装箱池”的大小
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 } }
设置-XX:AutoBoxCacheMax=<size>
在eclipse中,选中源文件,右键Run as—>RunConfiguratio--->Arguments,在VM arguments中做以下设置:
![](http://img.my.csdn.net/uploads/201301/17/1358391369_3931.jpg)
相关文章推荐
- Java编程之自动装箱与拆箱
- java 自动装箱与拆箱 中的陷阱
- Java自动装箱与拆箱及其陷阱
- java自动装箱、拆箱——Integer细节
- Java高新技术【1】 (静态导入-可变参数-增强for循环-基本数据类型的自动拆箱与装箱)
- Java 自动装箱与拆箱(Autoboxing and unboxing)
- 说说java的自动装箱(autoboxing)和拆箱(unboxing
- java 自动装箱与拆箱 (基本类型与包装类型)
- Java高新技术【1】 (静态导入-可变参数-增强for循环-基本数据类型的自动拆箱与装箱)
- Java 基本数据封装类自动装箱与拆箱
- java 自动装箱与拆箱 中的陷阱
- java基本类型自动装箱与拆箱
- 黑马程序员——Java1.5新特性之享元模式、增强for循环、可变参数、静态导入、自动装箱和拆箱
- JAVA自动装箱与拆箱
- (黑马程序员)Java基础加强(第一天)05-java5的静态导入和自动装箱拆箱
- Java中基本数据类型的自动拆箱和装箱
- JAVA1.5新特性----基本数据类型的自动拆箱与装箱
- java自动装箱与拆箱
- java高新技术之自动装箱拆箱
- java 易错点: 自动装箱与自动拆箱