标签:
装箱和拆箱之前,我们先来了解一下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 |
\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 |
9 | void |
--- | --- | --- | Void |
(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);
(2)跟的方向相反,将Integer及Double这样的引用类型的对象重新简化为基本类型的数据。
如下:
//这是拆箱
编译器内部会调用int intValue()返回该Integer对象的int值
代码如下:
反编译一下看得更清楚:
下面我们看看Integer源码中是怎么在内部缓存数值的。
/**
* Cache to support theobject identity semantics of autoboxing for values between
* -128 and 127(inclusive) as required by JLS.
*
* The cache isinitialized on first usage. During VM initialization the
* getAndRemoveCachePropertiesmethod may be used to get and remove any system
* properites thatconfigure the cache size. At this time, the size of the
* cache may be controlledby the vm option -XX:AutoBoxCacheMax=<size>.
*/
在eclipse中,选中源文件,右键Run as—>RunConfiguratio--->Arguments,在VM arguments中做以下设置:
运行,控制台报错:Unrecognized VM option ‘AutoBoxCacheMax=256‘
网上找到http://rednaxelafx.iteye.com/blog/680746这篇文章,里面解释的很清楚,使用Oracle/SunJDK 6,在server模式下,使用-XX:AutoBoxCacheMax=NNN参数即可将Integer的自动缓存区间设置为[-128,NNN]。这个参数是server模式专有的。而我使用的是HotSpot Client VM,那怎么切换成server模式呢?网上找到http://www.iteye.com/topic/857587这篇文章也很好的解决了我的问题,网上牛人好多啊,学习了。
虚拟机版本与模式查看:
java -version //查看JVM默认的环境
java -client -version //查看JVM的客户端环境,针对GUI优化,启动速度快,运行速度不如server
java -server -version //查看JVM的服务器端环境,针对生产环境优化,运行速度快,启动速度慢
我的虚拟机默认版本如下:
需要切换到
切换方法如下:
找到JAVA_HOME/jre/lib/i386/jvm.cfg,这就是JVM默认的查找顺序,内容如下
-client KNOWN
-server KNOWN
-hotspot ALIASED_TO -client
-classic WARN
-native ERROR
-green ERROR
只需要把-server和-clent换个位置就行了.如下
-server KNOWN
-client KNOWN
-hotspot ALIASED_TO -client
-classic WARN
-native ERROR
-green ERROR
最后运行,得到如下结果:
Integer integer1 = 100;
Integer integer2 = 100;
System.out.println("integer1==integer2: " + (integer1 == integer2));// true 自动装箱的两个缓存中的 Integer对象的引用比较
System.out.println("integer1.equals(integer2): " + (integer1.equals(integer2)));// true
System.out.println("integer1.compare(integer2): " + integer1.compareTo(integer2));// 0
Integer integer3 = 200;
Integer integer4 = 200;
System.out.println("integer3==integer4: " + (integer3 ==integer4)); // true 自动装箱的两个new Integer的引用比较
System.out.println("integer3>integer4: " + (integer3 > integer4)); // false将两个对象拆箱,再比较大小
System.out.println("integer3.equals(integer4): " + (integer3.equals(integer4)));// true
System.out.println("integer3.compare(integer4): " + integer3.compareTo(integer4));// 0
Integer integer5 =new Integer(100);
Integer integer6 =new Integer(100);
System.out.println("integer5==integer6: " + (integer5 == integer6));// false两个不同的Integer对象引用的比较
System.out.println("integer5.equals(integer6): " + (integer5.equals(integer6)));// true
System.out.println("integer5.compare(integer6): " + integer5.compareTo(integer6));// 0
intint1 = 100;
System.out.println("integer1==int1: " + (integer1 == int1));// true Integer缓存对象拆箱后与int比较
System.out.println("integer1.equals(int1): " + (integer1.equals(int1)));// true
System.out.println("integer1.compare(int1): " + integer1.compareTo(int1));// 0
intint2 = 200;
System.out.println("integer3==int2: " + (integer3 == int2));// true Integer对象拆箱后与int比较
System.out.println("integer3.equals(int2): " + (integer3.equals(int2)));// true
System.out.println("integer3.compare(int2): " + integer3.compareTo(int2));// 0
可以看到黄色那行和3的测试结果相比,结果变成了true,说明-XX:AutoBoxCacheMax=<size>这个选项真的可以改变Integer的缓存大小。
参见《The Java™Language Specification Java SE 7Edition 5.1.7》Boxing Conversion的描述
If the valuepbeing boxed is true, false, a byte, or a char inthe range \u0000 to \u007f,or an int or short numberbetween -128 and 127 (inclusive),then letr1andr2be the results of any two boxing conversions ofp. It is always the case thatr1==r2.
Byte,Short,Long对应的是-128~127
Character对应的是0~127
Float和Double没有自动装箱池
Java使用自动装箱和拆箱机制,节省了常用数值的内存开销和创建对象的开销,提高了效率。通过上面的研究和测试,结论如下:
(1)Integer和 int之间可以进行各种比较;Integer对象将自动拆箱后与int值比较
(2)两个Integer对象之间也可以用>、<等符号比较大小;两个Integer对象都拆箱后,再比较大小
(3) 两个Integer对象最好不要用==比较。因为:-128~127范围(一般是这个范围)内是取缓存内对象用,所以相等,该范围外是两个不同对象引用比较,所以不等。
以上是我个人学习和研究结论,如有不正确之处,欢迎大家指正。
标签:
原文地址:http://www.cnblogs.com/wxgblogs/p/5799596.html