Java自动装箱与拆箱及其陷阱分析

合集下载

Java中的包装类 装箱和拆箱

Java中的包装类 装箱和拆箱

Java中的包装类装箱和拆箱在java中,数据类型总共可分为两大种,基本数据类型(值类型)和类类型(引用数据类型)。

基本类型的数据不是对象,不能作为对象调用其toString()、hashCode()、getClass()、equals()等等方法。

所以在java中,针对8种基本数据类型,提供了针对每个基本数据类型的包装类。

如下:所谓装箱,就是把基本类型用它们相对应的引用类型包起来,使它们可以具有对象的特质,如我们可以把int型包装成Integer类的对象,或者把double包装成Double,等等。

所谓拆箱,就是跟装箱的方向相反,将Integer及Double这样的引用类型的对象重新简化为值类型的数据。

//JDK1.5 之前使用手动方式进行装箱和拆箱的操作public class IntegerDemo{public static void main (String []agrs){int i=10;Integer j=new Integer(i); //手动装箱操作int i1=j.intValue();//手动拆箱操作System.out.println(i1*i1);}}; //output:100//JDK1.5之后可自动进行的装箱和拆箱的操作,比较方便public class IntegerDemo02{public static void main (String []agrs){int i=10Integer j=i;int k=j;System.out.println(++k);}}; //output:11包装类的另外一个比较有用的是可以将String 字符串类型转换为相应的基本数据类型。

下面以将String转为int为例:public class IntegerDemo04{public static void main (String[] args){String str="1500";try{int i=Integer.parseInt(str);System.out.println(++i);}catch (Exception e){e.printStackTrace(); //打印异常信息}}};// output: 1501如果在上述方法中str="15er00";则在调用parseInt方法时候会产生NumberFormatException异常,见JDK API中对该方法的描述:public static int parseInt(String s) throws NumberFormatException将字符串参数作为有符号的十进制整数进行解析。

自动装箱和自动拆箱原理

自动装箱和自动拆箱原理

自动装箱和自动拆箱原理今天咱们来唠唠编程世界里一个挺有趣的话题——自动装箱和自动拆箱。

这俩概念听起来是不是有点神秘兮兮的?别担心,让我用大白话给您讲明白。

咱们先来说说自动装箱。

想象一下,您正在编程,就好像在搭建一个神奇的数字城堡。

有时候您想把一个基本数据类型,比如说一个小小的整数 5 ,当成一个对象来处理。

这时候,自动装箱就像一个神奇的魔法,它能把这个简单的整数 5 瞬间变成一个 Integer 对象。

是不是很神奇?就好像给这个数字穿上了一件华丽的外衣,让它从一个“小透明”变成了一个有身份有地位的“贵族”。

那这个魔法是怎么实现的呢?其实呀,在幕后有一套聪明的机制在运作。

当您写下类似 `Integer num = 5;` 这样的代码时,编译器就会悄悄地施展魔法,帮您把这个基本类型的 5 包装成一个 Integer 对象,然后再赋值给 num 。

这一切都发生得如此自然,您甚至都感觉不到魔法的存在。

再来说说自动拆箱。

这就像是把那个穿上华丽外衣的数字又脱下来,变回原来简单朴素的样子。

比如说,您有一个 Integer 对象 `num` ,然后您要进行一些数学运算,像 `int result = num + 5;` 。

这时候,自动拆箱就登场啦!它会悄悄地把`num` 这个对象变回基本数据类型的整数,然后再进行加法运算。

是不是感觉特别贴心?就好像有个小精灵在背后默默地为您服务,让您的编程变得轻松又愉快。

自动装箱和自动拆箱可给咱们编程带来了不少方便呢!以前没有它们的时候,咱们得自己手动去做这些转换,麻烦得要死。

现在有了这两个小魔法,代码写起来那叫一个流畅,效率也提高了不少。

比如说,在集合框架里,像 ArrayList 这种东西,它可只能装对象。

要是没有自动装箱,您想把一个整数放进去,那可就得自己先手动把它变成对象,多累呀!有了自动装箱,您直接把整数往里扔就行,简单又省事。

不过呢,虽然自动装箱和自动拆箱很方便,但也不是完全没有缺点的。

java自动拆装箱

java自动拆装箱

Java自动装箱与自动拆箱弄清楚了关于String的比较之后,昨天突发奇想地冒出一些问题。

Java里面的每个基本类型(primitive type)都有对应的引用类型(包装类wrapper),哈,问题就是与这个有关滴~打开eclipse写了个Integer i=1; 没有报错(呃,俺不了解autoboxing...)。

然后又陆续写了一些乱七八糟的,出现了一些意外的结果。

纠结了很久,想起autoboxing,有的问题想清楚了有的还没有;回寝室的路上又想起autounboxing,今天上网查了查相关资料,算是弄明白了。

开始写的是:public class EqualsDemo{public static void main(String[] args) {int i1=1,i2=1;Integer iv1=1,iv2=1;Integer in1=new Integer(1),in2= new Integer(1);print("(1) " + (i1==i2)); //(1)print("(2) " + (iv1==iv2)); //(2)print("(3) " + (in1==in2)); //(3)print("(4) " + (i1==iv1)); //(4)print("(5) " + (i1==in1)); //(5)print("(6) " + (iv1==in1)); //(6)}static void print(Object obj){System.out.println(obj);}}输出结果:(1) true(2) true(3) false(4) true(5) true(6) false(1) true:明白,==比较基本类型的值,i1、i2都是int类型,值相等。

java装箱和拆箱的方法

java装箱和拆箱的方法

java装箱和拆箱的方法Java中的装箱和拆箱是指将基本数据类型转换为对应的包装类类型和将包装类类型转换为对应的基本数据类型的过程。

在Java中,基本数据类型是int、float、double、boolean等,而包装类类型是Integer、Float、Double、Boolean等。

装箱和拆箱的方法如下:1. 装箱装箱是将基本数据类型转换为对应的包装类类型。

Java中提供了两种装箱的方法:(1)使用包装类的构造方法进行装箱例如,将int类型的数值装箱为Integer类型:int i = 10;Integer integer = new Integer(i);(2)使用valueOf()方法进行装箱例如,将int类型的数值装箱为Integer类型:int i = 10;Integer integer = Integer.valueOf(i);2. 拆箱拆箱是将包装类类型转换为对应的基本数据类型。

Java中提供了两种拆箱的方法:(1)使用包装类的xxxValue()方法进行拆箱例如,将Integer类型的数值拆箱为int类型:Integer integer = new Integer(10);int i = integer.intValue();(2)使用自动拆箱进行拆箱自动拆箱是指在需要基本数据类型的地方,自动将包装类类型转换为对应的基本数据类型。

例如:Integer integer = new Integer(10);int i = integer;需要注意的是,在使用自动拆箱时,如果包装类对象为null,则会抛出NullPointerException异常。

总结:Java中的装箱和拆箱是将基本数据类型和包装类类型相互转换的过程。

装箱可以使用包装类的构造方法或valueOf()方法,拆箱可以使用包装类的xxxValue()方法或自动拆箱。

在使用自动拆箱时,需要注意包装类对象是否为null。

自动装箱拆箱的作用

自动装箱拆箱的作用

自动装箱拆箱的作用
自动装箱和拆箱是Java语言中的概念,它们的作用是方便程序
员在基本数据类型和对应的包装类之间进行转换。

在Java中,基本
数据类型(如int、double等)和对应的包装类(如Integer、Double等)之间可以相互转换,而自动装箱和拆箱就是为了简化这
一过程而引入的概念。

自动装箱指的是将基本数据类型自动转换为对应的包装类对象,而自动拆箱则是将包装类对象自动转换为对应的基本数据类型。

这样,程序员在使用基本数据类型和包装类时就无需手动进行类型转换,使得代码更加简洁和易读。

举个例子,当我们需要将一个int类型的变量赋值给Integer
类型的对象时,可以直接进行赋值操作,而不需要调用Integer类
的构造函数进行手动转换。

这就是自动装箱的作用。

同样地,当我
们需要将一个Integer类型的对象赋值给int类型的变量时,也可
以直接进行赋值操作,而不需要调用intValue()方法进行手动转换,这就是自动拆箱的作用。

除了赋值操作,自动装箱和拆箱还可以在方法参数传递、方法
返回值等场景中发挥作用,使得代码编写更加便捷和简单。

总的来说,自动装箱和拆箱的作用是简化基本数据类型和包装类之间的转换过程,提高代码的可读性和易用性。

它们使得程序员在使用基本数据类型和包装类时更加方便,同时也减少了一些不必要的代码编写。

自动装箱和自动拆箱源码分析概论

自动装箱和自动拆箱源码分析概论

自动装箱(boxing)和自动拆箱(unboxing)首先了解下Java的四类八种基本数据类型自动装箱Java中所谓的装箱通俗点就是:八种基本数据类型在某些条件下使用时,会自动变为对应的包装器类型。

如下清单1:输出:解释下清单1第11句输出true的原因:当包装器类型进行“==”比较时,i3会调用Integer.valueOf自动装箱基本数据类型为包装器类型。

从源码中可以看出,Integer对象自动缓存int值范围在low~high(-128~127),如果超出这个范围则会自动装箱为包装类。

Note:1.Integer、Short、Byte、Character、Long这几个包装类的valueOf方法的实现是类似的;2.Double、Float的valueOf方法的实现是类似的。

3.Boolean的valueOf方法的实现是个三目运算,形如` return (b ? TRUE : FALSE); `自动拆箱Java中所谓的拆箱通俗点就是:八种包装器类型在某些条件下使用时,会自动变为对应的基本数据类型。

清单2:输出:解释下清单2第10句输出true的原因:当程序执行到第10句时,i4会调用Integer.intValue方法自动拆箱包装器类型为基本数据类型。

从源码可以看出,当包装器类型和基本数据类型进行“==”比较时,包装器类型会自动拆箱为基本数据类型。

清单3内容如下:输出:解释第15句为什么会输出true:因为在Integer包装类实现的equals方法中,只要比较的当前对象是Integer实例,那么就会自动拆箱为基本数据类型。

从以下Integer类的equals方法的源码就可看出:Note:1.Integer、Short、Byte、Character、Long这几个包装类的intValue方法的实现是类似的;2.Double、Float的intValue方法的实现是类似的。

3.Boolean的booleanValue方法的实现和intValue方法的实现也是类似的。

java中装箱和拆箱的概念

java中装箱和拆箱的概念

在Java中,装箱和拆箱是指将基本类型和对应的包装类之间进行相互转换的过程。

装箱(Boxing)是指将基本类型转换为对应的包装类的过程。

在Java中,包装类通常是以大写字母开头的类,如Integer、Double、Boolean等。

通过装箱,我们可以将基本类型值转换为相应的包装类对象,从而可以调用包装类中的方法或使用包装类中的属性。

拆箱(Unboxing)是指将包装类转换为对应的基本类型的过程。

通过拆箱,我们可以将包装类对象转换为相应的基本类型值,从而可以对其进行操作。

下面是一个示例,演示了装箱和拆箱的过程:
java复制代码
int num = 10;
Integer i = num; // 装箱
double result = i.doubleValue(); // 调用包装类方法
int num2 = (int) result; // 拆箱
在上面的示例中,将基本类型int转换为对应的包装类Integer,这是装箱过程。

然后,调用包装类方法doubleValue(),将包装类对象转换为double类型,这是拆箱过程。

最后,将double类型的result转换为int类型,这是再次拆箱的过程。

需要注意的是,在Java中,自动装箱和自动拆箱可以简化装箱和拆箱的过程。

自动装箱是指将基本类型转换为对应的包装类对象,自动拆箱是指将包装类对象转换为对应的基本类型值。

【IT专家】详解Java的自动装箱与拆箱(Autoboxing and unboxing)

【IT专家】详解Java的自动装箱与拆箱(Autoboxing and unboxing)

详解Java 的自动装箱与拆箱(Autoboxing and unboxing) 2015/09/22 5010 一、什么是自动装箱拆箱很简单,下面两句代码就可以看到装箱和拆箱过程//自动装箱Integer total = 99;//自定拆箱int totalprim = total; 简单一点说,装箱就是自动将基本数据类型转换为包装器类型;拆箱就是自动将包装器类型转换为基本数据类型。

下面我们来看看需要装箱拆箱的类型有哪些:这个过程是自动执行的,那么我们需要看看它的执行过程:public class Main { public static void main(String[] args) { //自动装箱Integer total = 99; //自定拆箱int totalprim = total; }} 反编译class 文件之后得到如下内容:javap -c StringTestInteger total = 99; 执行上面那句代码的时候,系统为我们执行了:Integer total = Integer.valueOf(99);int totalprim = total; 执行上面那句代码的时候,系统为我们执行了:int totalprim= total.intValue();我们现在就以Integer 为例,来分析一下它的源码:1、首先来看看Integer.valueOf 函数public static Integer valueOf(int i) { return i = 128 || i -128 ? new Integer(i) : SMALL_VALUES[i + 128];} 它会首先判断i 的大小:如果i 小于-128 或者大于等于128,就创建一个Integer 对象,否则执行SMALL_VALUES[i + 128]。

首先我们来看看Integer 的构造函数:private final int value;public Integer(int value) { this.value = value;}public Integer(String string) throws NumberFormatException { this(parseInt(string));} 它里面定义了一个value 变量,创建一个Integer 对象,就会给这个变量初始化。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

Java自动装箱与拆箱及其陷阱分析
定义
大家在平时编写Java程序时,都常常以以下方式来定义一个Integer对象:
Integeri=100;
从上面的代码中,大家可以得知,i为一个Integer类型的引用,100为Java中的基础数据类型(primitivedatatype)。

而这种直接将一个基础数据类型传给其相应的封装类(wrapperclass)的做法,便是自动装箱(Autoboxing)。

在jdk1.5中,自动装箱首次被引入。

而在jdk1.5之前,如果你想要定义一个value为100的Integer对象,则需要这样做:
Integeri=newInteger(100);
原理
我们在以上代码“Integeri=100;”处打一个断点,跟踪一下。

接下来,我们可以看到,程序跳转到了Integer类的
valueOf(inti)方法中
/**
*Returnsa Integer instancerepresentingthespecified
*int value.
*Ifanew Integer instanceisnotrequired,thismethod
*shouldgenerallybeusedinpreferencetotheconstructor
*{@link#Integer(int)},asthismethodislikelytoyield
*significantlybetterspaceandtimeperformancebycaching *frequentlyrequestedvalues.
*
*@paramian int value.
*@returna Integer instancerepresenting i.
*@since1.5
*/
publicstaticIntegervalueOf(inti){
if(i>=-128&&i<=IntegerCache.high)
returnIntegerCache.cache[i+128];
else
returnnewInteger(i);
}
换句话说,装箱就是jdk自己帮你完成了调用
Integer.valueOf(100)。

定义
Integerinteger100=100;
intint100=integer100;
从上面的代码中,大家可看出integer100为一个Integer类型的引用,int100为一个int类型的原始数据类型。

但是,我们可以将一个Integer类型的对象赋值给其相应原始数据类型的变量。

这便是拆箱。

拆箱与装箱是相反的操作。

装箱是将一个原始数据类型赋值给相应封装类的变量。

而拆箱则是将一个封装类的变量赋值给相应原始数据类型的变量。

装箱、拆箱的名字也取得相当贴切。

原理
笔者相信大家也都猜到了,拆箱过程中jdk为我们做了什么。

我们还是通过实验来证明我们的猜想吧。

在以上代码的第二行代码打上断点,即在
“intint100=integer100;”上打上断点,跟踪一下。

我们可以看到,程序跳转到了Integer的intValue()方法。

/**
*Returnsthevalueofthis Integer asan
*int.
*/
publicintintValue(){
returnvalue;
}
也就是,jdk帮我们完成了对intValue()方法的调用。

对于以上的实验而言,便是调用integer100的intValue()方法,将其返回值赋给了int100。

实验1
Integerinteger400=400;
intint400=400;
System.out.println(integer400==int400);
在以上代码的第三行中,integer400与int400执行了==运行。

而这两个是不同类型的变量,到底是integer400拆箱了,还是int400装箱了呢?运行结果是什么呢?
==运算是判断两个对象的地址是否相等或者判断两个基础数据类型的值是否相等。

所以,大家很容易推测到,如果integer400拆箱了,则说明对比的是两个基础类型的值,那此时必然相等,运行结果为true;如果int400装箱了,则说明对比的是两个对象的地址是否相等,那此时地址必然不相等,运行结果为false。

(至于为什么笔者对它们赋值为400,就是后面将要讲到的陷阱有关)。

我们实际的运行结果为true。

所以是integer400拆箱了。

对代码跟踪的结果也证明这一点。

实验2
Integerinteger100=100;
intint100=100;
System.out.println(integer100.equals(int100));
在以上代码的第三行中,integer100的方法equals的参数为int100。

我们知道equals方法的参数为Object,而不是基础数据类型,因而在这里必然是int100装箱了。

对代码跟踪的结果也证明了这一点。

其实,如果一个方法中参数类型为原始数据类型,所传入的参数类型为其封装类,则会自动对其进行拆箱;相应地,如果一个方法
中参数类型为封装类型,所传入的参数类型为其原始数据类型,则会自动对其进行装箱。

实验3
Integerinteger100=100;
intint100=100;
Longlong200=200l;
System.out.println(integer100+int100);
System.out.println(long200==(integer100+int100));
System.out.println(long200.equals(integer100+int100));
在第一个实验中,我们已经得知,当一个基础数据类型与封装类进行==运算时,会将封装类进行拆箱。

那如果+、-、*、/呢?我们在这个实验中,就可知道。

如果+运算,会将基础数据类型装箱,那么:
?第4行中,integer100+int100就会得到一个类型为Integer 且value为200的对象o,并执行这个对象的toString()方法,并输出”200”;
?第5行中,integer100+int100就会得到一个类型为Integer 且value为200的对象o,==运算将这个对象与long200对象进行对比,显然,将会输出false;
?第6行中,integer100+int100就会得到一个类型为Integer 且value为200的对象o,Long的equals方法将long200与o对比,因为两都是不同类型的封装类,因而输出false;
如果+运算,会将封装类进行拆箱,那么:
?第4行中,integer100+int100就会得到一个类型为int且value为200的基础数据类型b,再将b进行装箱得到o,执行这个对象的toString()方法,并输出”200”;
?第5行中,integer100+int100就会得到一个类型为int且value为200的基础数据类型b1,==运算将long200进行拆箱得到b2,显然b1==b2,输出true;
?第6行中,integer100+int100就会得到一个类型为int且value为200的基础数据类型b,Long的equals方法将b进行装箱,但装箱所得到的是类型为Integer的对象o,因为o与long200为不同的类型的对象,所以输出false;
程序运行的结果为:
200
true
false
因而,第二种推测是正确,即在+运算时,会将封装类进行拆箱。

相关文档
最新文档