java自动装箱拆箱总结
对于java1.5引入的自动装箱拆箱,之前只是知道一点点,最近在看一篇博客时发现自己对自动装箱拆箱这个特性了解的太少了,所以今天研究了下这个特性。以下是结合测试代码进行的总结。
测试代码:
int a = 1;
Integer b = 1;
Integer c = 1;
Integer d = 2;
Integer e = 3;
Integer f = 128;
Integer g = 128;
Long h = 3L;
Double m = 4.0;
Double n = 4.0;
Float p = 5f;
Float q = 5f;
System.out.println("a == b : " + (a == b)); //true
System.out.println("b ==c : " + (b == c)); //true
System.out.println("e == (c + d) : " + (e == (c + d))); //true
System.out.println("e.equals(c + d) : " + (e.equals(c + d))); //true
System.out.println("h == (c + d) : " + (h == (c + d))); //true
System.out.println("h.equals(c + d) : " + (h.equals(c + d))); //false
System.out.println("f == g : " + (f == g)); //false
System.out.println("m == n : " + (m == n)); //false
System.out.println("p == q : " + (p == q)); //false
System.out.println("m == d * 2 : " + (m == d * 2)); //true
System.out.println("p == (d + e) : " + (p == (d + e))); //true
测试输出结果与说明:
1. a == b : true
当基本类型包装类与基本类型值进行==运算时,包装类会自动拆箱。即比较的是基本类型值。
具体实现上,是调用了Integer.intValue()方法实现拆箱。
可以在测试代码处打断点,使用F5快捷键step
into至每一步执行方法,会看到调用了Integer.intValue()方法实现了拆箱。
2. b == c : true
b和c类型均为Integer包装类,故对基本类型进行自动装箱后赋值给b和c。
在进行==运算时不会触发拆箱操作。所以比较的是引用地址,说明b和c是同一个对象。
java中自动装箱调用的是Integer.valueOf()方法实现的,可以像例1一样打断点验证。
为什么b和c 会是同一个对象呢?查看Integer.valueOf()方法实现即可知道,如下:
下面的代码中可以看到,对于-128至127这256个值,直接获取的IntegerCache中的值。
而IntegerCache是Integer中的一个静态内部类,
里面将-128至127(即一个字节所能表示的所有带符号值 -2^7至2^7-1)的包装类存在了一个数组中。
对于-128到127之间的数,直接从数组中获取,其他的数则使用new生成。所以此处输出true。
public static Integer valueOf(int i) {
if(i >= -128 && i <= IntegerCache.high)
return IntegerCache.cache[i + 128];
else
return new Integer(i);
}
private static class IntegerCache {
static final int high;
static final Integer cache[];
static {
final int low = -128;
// high value may be configured by property
int h = 127;
if (integerCacheHighPropValue != null) {
// Use Long.decode here to avoid invoking methods that
// require Integer's autoboxing cache to be initialized
int i = Long.decode(integerCacheHighPropValue).intValue();
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++);
}
3. e == (c + d) : true
包装类在执行加减乘除求余等运算时,会触发拆箱操作,故c、d拆箱后相加,
结果为基本类型;然后e与基本类型进行==运算,触发拆箱操作。
4. e.equals(c + d) : true
首先,c + d 拆箱运算得到基本类型值;然后当进行equals运算时,
会触发基本类型值的装箱操作,c + d 的结果会自动装箱为包装类;最后与e进行equals运算。
5. h == (c + d) : true
运算顺序与上面例3中一致,唯一区别是h自动拆箱是调用了Long.longValue()实现。
6. h.equals(c + d) : false
运算顺序与上面例4中一致,为false的原因在于c + d的运算结果自动装箱后类型为Integer,
而h的类型为Long,类型不一样,equals的结果为false。
7. f == g : false
请参考上面例2中的解释。
超出了-128至127的缓存范围,故在valueOf()方法中使用new生成了新对象。
8. m == n : false
p == q : false
与上面例子1、2中的结果不同,对于Boolean、Byte、Character、Short、Integer、Long六种基本类型,
对于一个字节以内的值-128到127(Boolean只有true和false)都实现了缓存机制。
不在此范围的数才在对应的valueOf()方法中new出一个新的对象。
但是对于Double和Float类型的浮点数据,在-128到127之间除了256个整数外还有无数的小数,
故java中没有实现Double和Float中一些数的缓存。
所以,对于Double和Float的自动装箱,都是new出新的对象。故此两例均输出false。
10. m == d * 2 : true
p == (d + e) : true
请参考例3和例5。
反编译后代码:
使用java反编译工具,对class字节码文件进行反编译,结果如下所示。从下面的反编译代码,我们可以看到java是如何实现自动装箱、拆箱的。
int a = 1;
Integer b = Integer.valueOf(1);
Integer c = Integer.valueOf(1);
Integer d = Integer.valueOf(2);
Integer e = Integer.valueOf(3);
Integer f = Integer.valueOf(128);
Integer g = Integer.valueOf(128);
Long h = Long.valueOf(3L);
Double m = Double.valueOf(4.0D);
Double n = Double.valueOf(4.0D);
Float p = Float.valueOf(5.0F);
Float q = Float.valueOf(5.0F);
System.out.println("a == b : " + (a == b.intValue()));
System.out.println("b ==c : " + (b == c));
System.out.println("e == (c + d) : " + (e.intValue() == c.intValue() + d.intValue()));
System.out.println("e.equals(c + d) : " + e.equals(Integer.valueOf(c.intValue() + d.intValue())));
System.out.println("h == (c + d) : " + (h.longValue() == c.intValue() + d.intValue()));
System.out.println("h.equals(c + d) : " + h.equals(Integer.valueOf(c.intValue() + d.intValue())));
System.out.println("f == g : " + (f == g));
System.out.println("m == n : " + (m == n));
System.out.println("p == q : " + (p == q));
System.out.println("m == d * 2 : " + (m.doubleValue() == d.intValue() * 2));
System.out.println("p == (d + e) : " + (p.floatValue() == d.intValue() + e.intValue()));
参考文章:
①Java 自动装箱和拆箱
②Java自动装箱与拆箱及其陷阱
③深入剖析Java中的装箱和拆箱
④四道Java基础题 你能对几道?
java自动装箱拆箱总结的更多相关文章
- JAVA自动装箱拆箱与常量池
java 自动装箱与拆箱 这个是jdk1.5以后才引入的新的内容,作为秉承发表是最好的记忆,毅然决定还是用一篇博客来代替我的记忆: java语言规范中说道:在许多情况下包装与解包装是由编译器自行完成的 ...
- Java 自动装箱/拆箱
自动装箱/拆箱大大方便了基本类型(8个基本类型)数据和它们包装类的使用 自动装箱 : 基本类型自动转为包装类(int >> Integer) 自动拆箱: 包装类自动转为基本类型(Integ ...
- Java自动装箱拆箱
一.装箱.拆箱定义 如果一个int型量被传递到需要一个Integer对象的地方,那么,编译器将在幕后插入一个对Integer构造方法的调用,这就叫做自动装箱.而如果一个Integer对象被放到需要in ...
- 深入理解Java自动装箱拆箱机制
1.自动装箱与拆箱的定义 装箱就是自动将基本数据类型转换为包装器类型(int-->Integer): 拆箱就是自动将包装器类型转换为基本数据类型(Integer-->int). Java中 ...
- 那些年一起踩过的坑 — java 自动装箱拆箱问题
坑在哪里? 我们都知道Java的八种基本数据类型:int, short, long, double, byte, char, float, boolean 分别有各自对应的包装类型:Integ ...
- Java 的自动装箱拆箱
Java 是面向对象的语言,其基本数据类型也就有了相对应的类,称为包装类.以下是基本数据类型对应的包装类: 基本数据类型 包装类 byte(1字节) Byte short(2字节) Short int ...
- Java八种基本数据类型的大小,以及封装类,自动装箱/拆箱的用法?
参考:http://blog.csdn.net/mazhimazh/article/details/16799925 1. Java八种基本数据类型的大小,以及封装类,自动装箱/拆箱的用法? 原始类型 ...
- java基础1.5版后新特性 自动装箱拆箱 Date SimpleDateFormat Calendar.getInstance()获得一个日历对象 抽象不要生成对象 get set add System.arrayCopy()用于集合等的扩容
8种基本数据类型的8种包装类 byte Byte short Short int Integer long Long float Float double Double char Character ...
- Java的自动装箱/拆箱
概述 自JDK1.5开始, 引入了自动装箱/拆箱这一语法糖, 它使程序员的代码变得更加简洁, 不再需要进行显式转换.基本类型与包装类型在某些操作符的作用下, 包装类型调用valueOf()方法将原始类 ...
随机推荐
- Python模块 - re
Python 的 re 模块(Regular Expression 正则表达式)提供各种正则表达式的匹配操作,在文本解析.复杂字符串分析和信息提取时是一个非常有用的工具,下面我主要总结了re的常用方法 ...
- 合并两个list,不包含重复的对象
package com.compare.test; import java.util.ArrayList;import java.util.Collections;import java.util.L ...
- 【BZOJ4034】【HAOI2015】树上操作
题目请自行查阅传送门. 典型的树剖题,线段树维护操作,记一下子树在线段树内范围即可. 时间复杂度:\( O(m \log^{2} n) \) #include <stdio.h> #def ...
- ●POJ 1329 Circle Through Three Points
题链: http://poj.org/problem?id=1329 题解: 计算几何,求过不共线的三点的圆 就是用向量暴力算出来的东西... (设出外心M的坐标,由于$|\vec{MA}|=|\ve ...
- hdu 5314 动态树
Happy King Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 262144/262144 K (Java/Others)Tot ...
- VK Cup 2017 - Квалификация 1
CF上的VK Cup 2017资格赛1,好像很水,因为只有俄文所以语言是最大的障碍--不过之后正式赛貌似就有英文了.(比赛貌似只有开俄文模式才看的到--) 时长1天,不随时间扣分.FallDream ...
- Codeforces 671 D. Roads in Yusland
题目描述 Mayor of Yusland just won the lottery and decided to spent money on something good for town. Fo ...
- c++中成员函数的参数名与成员变量名重合的问题
有一天写类的时候突然想到了这个问题,下面就来介绍如何解决这个问题. 定义一个类: class test{ public: void setnum(); void getnum(); private: ...
- python中int的功能简单介绍
Int的功能介绍 1. 绝对值 x.__abs__()等同于abs(x) 2. 加法 x.__add__(y)等同于x+y 3. 与运算 x.__and__(y)等同于x&y 4. 布尔运算 ...
- Mysql优化--慢查询日志
Mysql 系列文章主页 =============== 默认没有开启慢查询日志功能.如果不是调优需要的话,一般不建议开启. 查看是否开启慢查询日志: SHOW VARIABLES LIKE '%sl ...