Integer 与 int -- 自动装箱(autoboxing)与自动拆箱(unboxing)
-
转载于 http://www.ticmy.com/?p=110
jdk1.5引入了自动装箱(autoboxing)与自动拆箱(unboxing),这方便了集合类以及一些方法的调用,同时也使初学者对其感到非常之困惑。在此,我们来揭开其神秘的面纱。
首先,需要厘清一些概念:
1、Integer是一个类,用Integer声明一个变量其是一个对象类型(或者说引用类型);int是基本类型,用int声明的变量是非对象类型,即不能在其上调用方法。
2、“==”作用于对象上的时候,其比较的是对象的引用本身的值(或者说对象的地址更容易理解),而作用于基本类型的时候比较的就是基本类型的值。接下来看一段代码:
public
class
Test {
public
static
void
main(String[] args) {
Integer i1 =
2
;
int
i2 =
2
;
System.out.println(i1 == i2);
}
}
在这段代码中有两个令人困惑的问题,首先是将一个基本类型的值赋值给对象的引用,即Integer i1 =2;其次是拿一个对象类型和一个基本类型比较。按理说这两种做法肯定都是有问题的,在jdk1.4(若使用的jdk版本是1.5或之后的版本中,可以使用javac -source 1.4 Test.Java来编译)上,确实如此,第一个问题在编译时会报“不兼容的类型”错误,第二个问题会报“运算符 == 不能应用于 java.lang.Integer,int”的错误。
但是jdk1.5引入的自动装箱和自动拆箱,那么,必然要将其中的一种类型转换成另一种类型,究竟是将Integer对象i1转换成int基本类型呢?还是将int基本类型的i2转换成Integer对象?通过javap -c Test反编译Test.class文件就知道答案了:
public
static
void
main(java.lang.String[]);
Code:
0
: iconst_2
1
: invokestatic #
2
;
//Method
java/lang/Integer.valueOf:(I)Ljava/lang/Integer;4
: astore_1
5
: iconst_2
6
: istore_2
7
: getstatic #
3
;
//Field
java/lang/System.out:Ljava/io/PrintStream;10
: aload_1
11
: invokevirtual #
4
;
//Method
java/lang/Integer.intValue:()I14
: iload_2
15
: if_icmpne
22
18
: iconst_1
19
:
goto
23
22
: iconst_0
23
: invokevirtual #
5
;
//Method
java/io/PrintStream.println:(Z)V26
:
return
}
其中,[0-4]是Integer i1 = 2的实现,我们发现,编译的字节码里调用了Integer.valueOf方法,因此Integer i1 = 2编译后就等同于Integer i1 = Integer.valueOf(2);[5,6]是int i2 = 2的实现;[7,23]是System.out.println(i1 == i2)的实现,也容易看到,里面调用了Integer.intValue()方法。因此,这个i1 == i2这两个不同类型的变量比较,在编译的时候,编译器是将其转换成相同的类型进行比较的,即将对象类型转换成基本类型,System.out.println(i1 == i2)就等同于System.out.println(i1.intValue() == i2),前面说了,“==”作用于基本类型的时候比较的就是基本类型的值,两个值都是2,所以结果是true。
另外一个令人困惑的例子就是:
public
class
Test {
public
static
void
main(String[] args) {
Integer i1 =
127
;
Integer i2 =
127
;
System.out.println(i1 == i2);
Integer i3 =
128
;
Integer i4 =
128
;
System.out.println(i3 == i4);
}
}
运行后发现,i1==i2的结果为true,i3==i4的结果为false?这令不知原因的人头疼不已。在前面一个例子里我们已经说过,诸如Integer i1 = 127,在编译后就等同于Integer i1 = Integer.valueOf(127),既然是调用一个方法来获得对象,那么就有必要对valueOf方法一探究竟了。我们看下源码:
public
static
Integer valueOf(
int
i) {
final
int
offset =
128
;
if
(i >= -
128
&& i <=
127
)
{// must cache
return
IntegerCache.cache[i + offset];
}
return
new
Integer(i);
}
到此应该恍然大悟了,IntegerCache缓存了[-128,127]之间的Integer对象,如果valueOf的参数i处于这之间,就返回缓存的对象。否则就new一个新的Integer。前面已经说过,“==”作用于对象上的时候,其比较的是对象的地址,例子中的i1和i2都是从缓存中拿的,当然是同一个对象,i3和i4都是通过new Integer获得的,当然不是同一个对象了。
类似地,java.lang.Long,java.lang.Short分别缓存了[-128,127]之间的Long和Short对象,java.lang.Byte缓存了所有的对象,java.lang.Character缓存了[0,127]之间的Character对象。java缓存这些对象是为了性能优化,既然我们已经知道其缓存了这么些对象,在需要new Integer/Long/…的地方,可改用Integer/Long/Short…#valueOf方法。
但是:使用Oracle/Sun JDK 6,在server模式下,使用-XX:AutoBoxCacheMax=NNN参数即可将Integer的自动缓存区间设置为[-128,NNN]。注意区间的下界固定在-128不可配置。
在client模式下该参数无效。这个参数是server模式专有的,在c2_globals.hpp中声明,默认值是128;不过这个默认值在默认条件下不起作用,要手动设置它的值或者是开启-XX:+AggressiveOpts参数才起作用。
Integer 与 int -- 自动装箱(autoboxing)与自动拆箱(unboxing)的更多相关文章
- 【C#】 装箱 (boxing) 和拆箱 (unboxing)
目录: 1. 装箱和拆箱 2. 深入理解装箱和拆箱 3. int[] to object[],值类型数组到对象数组的转化 4. 使用泛型减少装箱和拆箱 1. 装箱和拆箱 装箱 就是把“值类型”转换成 ...
- C#中的装箱(inboxing)和拆箱(unboxing)(简单理解)
装箱和拆箱是值类型和引用类型之间相互转换是要执行的操作. 装箱:将一个值类型隐式地转换成一个object类型,或把这个值类型转换成一个被该值类型应用的接口类型,把一个值类型的值装箱,就是创建一个ob ...
- int和Integer的自动拆箱/装箱相关问题
java中为没一种基本类型都提供相应的包装类型. byte,short,char,int,long,float,double和boolean Byte,Short,Character,Integer, ...
- Java连载77-Integer常用方法、Integer、int、String三者相互转化、自动装箱、自动拆箱
一.关于Integer中常用的方法 package com.bjpowernode.java_learning; public class D77_1_ { public static void ...
- Java 自动装箱与拆箱(Autoboxing and unboxing)
什么是自动装箱拆箱 基本数据类型的自动装箱(autoboxing).拆箱(unboxing)是自J2SE 5.0开始提供的功能. 一般我们要创建一个类的对象实例的时候,我们会这样: Class a = ...
- Java 性能要点:自动装箱/ 拆箱 (Autoboxing / Unboxing)
[编者按]本文作者为 Ali Kemal TASCI,最早于2016年4月9日发布于DZONE社区.文章主要介绍通过改进 Java 1.5 就已存在的骨灰级特性大幅度提高应用性能. 本文系 OneAP ...
- Java 自动装箱与拆箱(Autoboxing and unboxing)
什么是自动装箱拆箱 基本数据类型的自动装箱(autoboxing).拆箱(unboxing)是自J2SE 5.0开始提供的功能. 一般我们要创建一个类的对象实例的时候,我们会这样: Class a = ...
- 转:Java 自动装箱与拆箱(Autoboxing and unboxing)
转: http://www.cnblogs.com/danne823/archive/2011/04/22/2025332.html 什么是自动装箱拆箱 基本数据类型的自动装箱(autoboxing) ...
- 自动装箱拆箱(Autoboxing,Unboxing)
自动装箱和拆箱 https://docs.oracle.com/javase/tutorial/java/data/autoboxing.html 1.5才有(Autoboxing,Unboxing) ...
- Java暗箱操作之自动装箱与拆箱
我以前在写Android项目的时候,估计写得最多最熟练的几句话就是: List<Integer> list = new ArrayList<Integer>(); list.a ...
随机推荐
- 常用脚本--归档ERRORLOG
SQL Server error log 7组日志文件默认情况下不会自动切换到下一个文件, 一般在SQL Server 重新启动后才会切换error log,如果SQL Server长期未重启或因为 ...
- C/C++内存泄露及检测工具
内存泄漏的定义 一般我们常说的内存泄漏是指堆内存的泄漏.堆内存是指程序从堆中分配的,大小任意的(内存块的大小可以在程序运行期决定),使用完后必须显示释放的内 存.应用程序一般使用malloc,re ...
- WPF 按名称查找控件
1FrameworkElement类FindName方法 使用过程 1.容器控件.RegisterName("Name",要注册的控件) //注册控件 2.容器控件.FindN ...
- 基于ASP.NET的MVC框架下的MvcPaper分页控件的使用技术
using System; using System.Collections.Generic; using System.Linq; using System.Web; using Webdiyer. ...
- form-inline+form-group 实现表单横排显示(Bootstrap)
运行后的效果如下: 使用时要注意如下: 如果form元素有form-line修饰,那么form-group 所修饰的元素内部只能包含一个元素,否则,不会达到预期效果
- 由button标签在 IE 8.0 下的异常表现引发的一场血案
写在最前的最后:整篇文章絮絮叨叨说了半天,我得出一个最佳实践:和button标签say goodbay,用 a 标签模拟之. 首先看一个在chrome 下的简单demo 这样的布局在组件开发中再常见不 ...
- 实例的初始化由JVM装载类的时候进行,保证了线程的安全性
在23种设计模式中,单例是最简单的设计模式,但是也是很常用的设计模式.从单例的五种实现方式中我们可以看到程序员对性能的不懈追求.下面我将分析单例的五种实现方式的优缺点,并对其在多线程环境下的性能进行测 ...
- unittest测试框架和测试报告的输出实例(一)
我们整个自动化才是报告的环节基本上分为三个部分: 1.测试用例的准备 2.测试用例的执行 3.测试报告的输出 1.测试用例的准备: 那我们就以搜孤网页做一个简单的用例: from selenium i ...
- 谷歌将对欧洲 Android 设备制造商收取其应用服务费用
简评:欧盟就谷歌违反了<反垄断法>开出天价罚单,导致谷歌运营生态被打破,为了配合这一裁决,谷歌将调整其运营模式.欧盟似乎赢了,而这最后买单的却是消费者. 今年七月份,谷歌要求 Androi ...
- max,min无法使用的问题
遇到了包含algorithm头文件以后 min或max函数不能用的问题 改成__min和__max以后就可以了