JVM学习笔记--语法糖之 自动装箱的陷阱
2011-11-27 13:52
246 查看
JVM的自动装箱、自动拆箱语法糖看起来虽然简单,但也不见得就没有任何值得我们注意的地方,下面代码演示了自动装箱的一些错误用法:
上面代码的运行结果如下:
这个结果也许出乎部分人的意料,这就是JVM自动装箱、自动拆箱语法糖在捣鬼。我们把上面的代码编译后的.class文件进行反编译,反编译后的源代码文件中的语法糖已经被擦除,详细如下:
从上面的反编译后的代码可以看出:包装类(如Integer类)的 “==”运算在没有遇到算术运算的情况下不会自动拆箱,且它们的equals()方法不会处理数据类型转换的关系。如:
也许有人会问,同样是没有自动拆箱,同样是对象之间的比较,且数值一样,为何c 与d,e与f之间的比较结果会不同呢?且看下面分析:
1.我们知道在JAVA中用“==”进行对象之间的比较时,如果两对象都指向同一个引用(内存空间地址),那么返回true,否则返回false。
2.我们来看看Integer.valueOf()方法的源码及说明:
结合1、2的说明,相信大家就明白为何是这种结果了。
综上所述,我们在实际编码过程中应该尽量避免这样来使用自动装箱与自动拆箱 语法糖。
public class SyntaxSugarTest { public static void main(String[] args) { Integer a = 1; Integer b = 2; Integer c = 3; Integer d = 3; Integer e = 128; Integer f = 128; Long g = 3L; System.out.println("c == d : " + (c == d)); System.out.println("e == f : " + (e == f)); System.out.println("c == (a + b) : " + (c == (a + b))); System.out.println("c.equals(a + b) : " + (c.equals(a + b))); System.out.println("g == (a + b) : " + (g == (a + b))); System.out.println("g.equals(a + b) : " + (g.equals(a + b))); } }
上面代码的运行结果如下:
c == d : true e == f : false c == (a + b) : true c.equals(a + b) : true g == (a + b) : true g.equals(a + b) : false
这个结果也许出乎部分人的意料,这就是JVM自动装箱、自动拆箱语法糖在捣鬼。我们把上面的代码编译后的.class文件进行反编译,反编译后的源代码文件中的语法糖已经被擦除,详细如下:
public class SyntaxSugarTest { public static void main(String[] args) { Integer a = Integer.valueOf(1); Integer b = Integer.valueOf(2); Integer c = Integer.valueOf(3); Integer d = Integer.valueOf(3); Integer e = Integer.valueOf(128); Integer f = Integer.valueOf(128); Long g = Long.valueOf(3L); System.out.println("c == d : " + (c == d)); System.out.println("e == f : " + (e == f)); System.out.println("c == (a + b) : " + (c.intValue() == a.intValue() + b.intValue())); System.out.println("c.equals(a + b) : " + c.equals(Integer.valueOf(a.intValue() + b.intValue()))); System.out.println("g == (a + b) : " + (g.longValue() == a.intValue() + b.intValue())); System.out.println("g.equals(a + b) : " + g.equals(Integer.valueOf(a.intValue() + b.intValue()))); } }
从上面的反编译后的代码可以看出:包装类(如Integer类)的 “==”运算在没有遇到算术运算的情况下不会自动拆箱,且它们的equals()方法不会处理数据类型转换的关系。如:
System.out.println("c == d : " + (c == d));//没有算术运算符,不会自动拆箱,因此仍然是对象之间的比较 System.out.println("e == f : " + (e == f));//原理同上,至于结果为何不同见下面分析 System.out.println("c == (a + b) : " + (c.intValue() == a.intValue() + b.intValue()));//有+运算,会自动拆箱,因此变为原子类型的普通数值比较
System.out.println("g.equals(a + b) : " + g.equals(Integer.valueOf(a.intValue() + b.intValue())));//不会自动处理类型转换
也许有人会问,同样是没有自动拆箱,同样是对象之间的比较,且数值一样,为何c 与d,e与f之间的比较结果会不同呢?且看下面分析:
1.我们知道在JAVA中用“==”进行对象之间的比较时,如果两对象都指向同一个引用(内存空间地址),那么返回true,否则返回false。
2.我们来看看Integer.valueOf()方法的源码及说明:
/** * Returns a <tt>Integer</tt> instance representing the specified * <tt>int</tt> value. * If a new <tt>Integer</tt> instance is not required, this method * should generally be used in preference to the constructor * {@link #Integer(int)}, as this method is likely to yield * significantly better space and time performance by caching * frequently requested values. * ========下文中的IntegerCache.high = 127(默认) high value may be configured by property * @param i an <code>int</code> value. * @return a <tt>Integer</tt> instance representing <tt>i</tt>. * @since 1.5 */ public static Integer valueOf(int i) { if(i >= -128 && i <= IntegerCache.high) return IntegerCache.cache[i + 128]; else return new Integer(i); }
//上文中的IntegerCache.high = 127(默认) high value may be configured by property
结合1、2的说明,相信大家就明白为何是这种结果了。
综上所述,我们在实际编码过程中应该尽量避免这样来使用自动装箱与自动拆箱 语法糖。
相关文章推荐
- 第五天04 JAVA基础语法(认识对象--自动装箱、拆箱、数组基础[一维、二维数组]、for循环、数组对象、字符串对象)(学习笔记)
- 黑马训练营java学习笔记:自动装箱与拆箱(AutoBoxing/unboxing)
- java学习笔记-自动装箱,自动拆箱
- Java学习笔记之JDK1.5新特性(四):自动装箱和自动拆箱
- Java学习笔记 --- 自动装箱与自动拆箱
- JAVA语法糖之自动装箱的陷阱
- Java学习笔记之自动装箱与拆箱
- Java学习笔记——自动装箱、拆箱 & String初始化
- JavaWeb学习笔记-java基础-3-自动装箱拆箱
- 深入理解JVM学习笔记-自动内存管理机制
- dotnet学习笔记一 - 装箱拆箱
- PHP学习笔记(2)-语法和数据类型
- javascript学习笔记-语法基础
- C# 学习笔记(一) -- 基本语法
- JVM学习笔记(一)------基本结构
- boost 学习笔记:regex语法规范(翻译)ZT
- Java 学习笔记 ------第三章 基础语法
- iOS-学习笔记-内存管理 (1)自动引用计数
- [转]JVM学习笔记(三)------内存管理和垃圾回收
- JVM学习笔记1-jvm的基本结构