自动装箱、拆箱与遍历循环(Foreach循环)
来源:互联网 发布:java按层次遍历二叉树 编辑:程序博客网 时间:2024/06/06 01:34
看如下例子:包含了自动装箱、拆箱以及foreach循环的过程
public static void main(String[] args) { List<Integer> list = Arrays.asList(1, 2, 3, 4); // 如果在JDK 1.7中,还有另外一颗语法糖 , // 能让上面这句代码进一步简写成List<Integer> list = [1, 2, 3, 4]; int sum = 0; for (int i : list) { sum += i; } System.out.println(sum);}
上面的程序内部编译后如下:
public static void main(String[] args) { List list = Arrays.asList( new Integer[] { Integer.valueOf(1), Integer.valueOf(2), Integer.valueOf(3), Integer.valueOf(4) }); int sum = 0; for (Iterator localIterator = list.iterator(); localIterator.hasNext(); ) { int i = ((Integer)localIterator.next()).intValue(); sum += i; } System.out.println(sum);}
上述代码一共包含了泛型、自动装箱、自动拆箱、遍历循环与变长参数5中语法糖,第二份代码是他们编译后的变化。泛型在编译过程中会进行擦除,将泛型参数去除;自动装箱、拆箱在变之后被转化成了对应的包装盒还原方法,如Integer.valueOf()与Integer.intValue()方法;而遍历循环则被还原成了迭代器的实现,这也是为什么遍历器循环需要被遍历的类实现Iterator接口的原因。
这些语法糖虽然看起来很简单,但也有一些应该注意容易犯错的地方。看如下代码:
public static void main(String[] args) { Integer a = 1; Integer b = 2; Integer c = 3; Integer d = 3; Integer e = 321; Integer f = 321; Long g = 3L; System.out.println(c == d); System.out.println(e == f); System.out.println(c == (a + b)); System.out.println(c.equals(a + b)); System.out.println(g == (a + b)); System.out.println(g.equals(a + b)); String str1 = "hello"; String str2 = "hello"; System.out.println(str1 == str2);}运行结果:truefalsetruetruetruefalsetrue
首先注意两点:
- “==”运算在不遇到算术运算的情况下不会自动拆箱。
- equals()方法不处理数据转型的问题。
分析:
- 为什么会出现c == d为true,e==f为false的原因?First,Integer c = 3这句代码的内部实现是Integer c = Integer.valueOf(3),那么接下我们看一下Integer.valueOf()的方法内部是如何实现的,如下代码:
public static Integer valueOf(int i) { if (i >= IntegerCache.low && i <= IntegerCache.high) return IntegerCache.cache[i + (-IntegerCache.low)]; return new Integer(i);}static final int low = -128;static final int high = 127;
从上面代码可以知道,在Java运行时内存的常量池里面有一个int类型的常量池,常量池里数据的大小在-128~127之间。所以c和d都指向常量池里的同一个数据。
为什么g == (a + b)为true,而g.equals(a + b)为false?
首先Long.longValue(g) == (a + b)编译后为g.longValue() == (long)(Integer.intValue(a) + Integer.intValue(a)),由于包装类的”==”右边遇到了运算符,所以对于”==”左边的Long型会自动拆箱为long基本数据类型,而右边首先对a、b进行自动拆箱,相加后自动类型转换为long型。所以输出为true。而对于g.equals(a + b)而言,a+b直接自动拆箱进行相加,之后进行装箱为Integer类型,不同类型的包装类不能相互转换,而Long的equals()方法的不处理数据类型的转型关系。实现如下:
public boolean equals(Object obj) { if (obj instanceof Long) { return value == ((Long)obj).longValue(); } return false;}
- 自动装箱、拆箱与遍历循环(Foreach循环)
- java语法糖自动装箱、拆箱与遍历循环
- foreach循环遍历控件
- foreach循环遍历
- Mybatis 循环遍历 foreach
- 黑马程序员-------(高新技术)静态导入、可变参数、增强for循环、基本数据类型的自动拆箱与装箱
- 静态导入-可变参数-增强for循环-基本数据类型的自动拆箱与装箱
- JavaSE第五十七讲:增强的for循环与自动装箱拆箱详解
- 黑马程序员_java增强for循环自动装箱与拆箱
- java5的静态导入与自动装箱拆箱,增强for循环
- 黑马程序员 十四、Eclipse 的使用、增强 for 循环、自动拆箱与装箱等
- 26、增强的for循环和自动装箱拆箱
- 26、增强的for循环和自动装箱拆箱
- java基础加强(枚举,反射,增强for循环,可变参数,自动拆箱装箱,内省)
- foreach循环及Map遍历
- javascript数组循环遍历forEach
- foreach循环遍历二维数组
- thinkphp5中foreach遍历循环
- Handler、Looper消息传递机制
- handle句柄
- Hadoop常用命令及常见问题
- 【Hibernate持续更新】映射组件关系
- 解读Unity中的CG编写Shader系列三
- 自动装箱、拆箱与遍历循环(Foreach循环)
- as中的证书指纹SHA1
- JHipster使用前的环境配置-JHipster学习(一)
- RMI浅尝辄止
- css-border:0;和border:none;
- 传智播客视频--junit测试架构的学习记录
- 如何评价 React Native?
- dom4j简明教程
- 使用 ConfigSource 特性 拆分 Web.config 文件