`
yangwn
  • 浏览: 77309 次
  • 性别: Icon_minigender_2
  • 来自: 大连
社区版块
存档分类
最新评论
  • icewubin: kimmking 写道icewubin 写道Dollyn 写道 ...
    Java
  • kimmking: icewubin 写道Dollyn 写道我十分怀疑最后一条,很 ...
    Java
  • beneo: 完全忽略了一個好的JVM的優化能力 難道java是C編譯器么 ...
    Java
  • icewubin: Dollyn 写道我十分怀疑最后一条,很多编译器都会自动做类似 ...
    Java
  • Dollyn: 我十分怀疑最后一条,很多编译器都会自动做类似优化吧(不知道JD ...
    Java

java 自动装箱与拆箱中的陷阱

    博客分类:
  • JAVA
阅读更多

自动装箱与拆箱的功能事实上是编译器来帮您的忙,编译器在编译时期依您所编写的语法,决定是否进行装箱或拆箱动作。例如:

Integer i = 100;相当于编译器自动为您作以下的语法编译:

Integer i = new Integer(100);所以自动装箱与拆箱的功能是所谓的“编译器蜜糖”(Compiler Sugar),虽然使用这个功能很方便,但在程序运行阶段您得了解Java的语义。例如下面的程序是可以通过编译的:

Integer i = null;int j = i;这样的语法在编译时期是合法的,但是在运行时期会有错误,因为这种写法相当于:

Integer i = null;int j = i.intValue();null表示i没有参考至任何的对象实体,它可以合法地指定给对象参考名称。由于实际上i并没有参考至任何的对象,所以也就不可能操作intValue()方法,这样上面的写法在运行时会出现NullPointerException错误。

自动装箱、拆箱的功能提供了方便性,但隐藏了一些细节,所以必须小心。再来看范例4.6,您认为结果是什么呢?

Ü 范例4.6 AutoBoxDemo2.java

public class AutoBoxDemo2 {

public static void main(String[] args) {

Integer i1 = 100;

Integer i2 = 100;

if (i1 == i2)

System.out.println("i1 == i2");

else

System.out.println("i1 != i2");

}

}

从自动装箱与拆箱的机制来看,可能会觉得结果是显示i1 == i2,您是对的。那么范例4.7的这个程序,您觉得结果是什么?

Ü 范例4.7 AutoBoxDemo3.java

public class AutoBoxDemo3 {

public static void main(String[] args) {

Integer i1 = 200;

Integer i2 = 200;

if (i1 == i2)

System.out.println("i1 == i2");

else

System.out.println("i1 != i2");

}

}

结果是显示i1 != i2,这有些令人惊讶,两个范例语法完全一样,只不过改个数值而已,结果却相反。

其实这与==运算符的比较有关,在第3章中介绍过==是用来比较两个基本数据类型的变量值是否相等,事实上==也用于判断两个对象引用名称是否参考至同一个对象。

在自动装箱时对于值从–128到127之间的值,它们被装箱为Integer对象后,会存在内存中被重用,所以范例4.6中使用==进行比较时,i1 与 i2实际上参考至同一个对象。如果超过了从–128到127之间的值,被装箱后的Integer对象并不会被重用,即相当于每次装箱时都新建一个 Integer对象,所以范例4.7使用==进行比较时,i1与i2参考的是不同的对象。

所以不要过分依赖自动装箱与拆箱,您还是必须知道基本数据类型与对象的差异。范例4.7最好还是依正规的方式来写,而不是依赖编译器蜜糖(Compiler Sugar)。例如范例4.7必须改写为范例4.8才是正确的。

Ü 范例4.8 AutoBoxDemo4.java

public class AutoBoxDemo4 {

public static void main(String[] args) {

Integer i1 = 200;

Integer i2 = 200;

if (i1.equals(i2))

System.out.println("i1 == i2");

else

System.out.println("i1 != i2");

}

}

结果这次是显示i1 == i2。使用这样的写法,相信也会比较放心一些,对于这些方便但隐藏细节的功能到底要不要用呢?基本上只有一个原则:如果您不确定就不要用。 

分享到:
评论

相关推荐

    浅谈Java自动装箱与拆箱及其陷阱

    Java中的自动装箱和拆箱是自JDK 1.5版本引入的一种语言特性,它极大地简化了基础数据类型(如int)与它们对应的包装类(如Integer)之间的转换过程。这一特性使得开发者无需手动创建包装类实例或使用显式类型转换,...

    java陷阱之自动装箱共2页.pdf.zip

    4. **集合操作与自动装箱**:当向集合中添加基本类型时,Java会自动将其装箱。然而,如果集合中存在重复的基本类型值,由于它们被装箱成不同的对象,所以不会被视为重复。因此,在使用Set存储基本类型时,应使用专门...

    Java中的装箱和拆箱深入理解

    Java中的装箱和拆箱是面向对象编程中的一个重要概念,主要涉及到基本数据类型与它们对应的包装器类之间的转换。在Java SE 5及以后的版本中,为了方便开发者使用,引入了自动装箱和拆箱的功能。 一、什么是装箱和...

    Java 自动转换的资源

    Java 自动转换是Java编程语言中的一个重要特性,它涉及到类型转换、自动装箱与拆箱、数据类型提升等多个方面。在Java中,自动转换极大地方便了开发人员处理不同类型的数据,提高了代码的可读性和效率。以下是关于...

    java解惑(源代码+教程)

    2. **自动装箱与拆箱**:Java 5引入了自动装箱和拆箱机制,使得基本类型和对应的包装类之间可以无缝切换。但这也可能隐藏潜在的性能问题,因为每次装箱和拆箱都会创建新的对象。 3. **字符串操作**:Java中的字符串...

    java笔记,java学习笔记

    Java支持自动装箱和拆箱,这是一种语法糖,允许程序员在基本数据类型和其对应的包装类之间自动转换。例如,`Integer i = 10;`是自动装箱的例子,而`int j = i;`则是自动拆箱的例子。需要注意的是,这种便利性也可能...

    java SE(入门知识4)原生数据类型使用陷阱.docx

    - 自从Java 5引入了自动装箱和拆箱机制,原始类型和它们对应的包装类之间可以方便地转换。例如,`Short a = 1;`实际上是将`int`类型的`1`自动装箱为`Short`对象。但需要注意的是,这种转换在某些情况下可能会导致...

    Java五道输出易错题解析(进来挑战下).pdf

    Java编程语言中包含...对于Java程序员来说,熟悉Unicode字符、类加载机制、装箱拆箱以及异常处理等概念至关重要。在实际开发中,时刻保持警惕,对代码进行详尽的测试和审查,能够帮助我们写出更加健壮和可靠的程序。

    良葛格java jdk 5.0学习笔记

    3. **自动装箱与拆箱**:为了简化编程,Java 5.0引入了自动装箱和拆箱机制,使得原始类型和其对应的包装类之间可以无缝转换。 4. **变量注解(Variable Annotations)**:除了类和方法,Java 5.0开始支持在变量声明...

    java解惑(java谜题)中文版的

    1. **类型转换**:Java中的自动装箱和拆箱可能导致一些陷阱,比如Integer对象与int基本类型的比较。在处理数值时,不恰当的类型转换可能导致逻辑错误。 2. **变量作用域**:Java的局部变量、成员变量和静态变量的...

    java-puzzlers-sampler_java_Joshua_

    1. **类型转换与自动装箱拆箱**:Java中存在基本类型与其对应的包装类,如`int`与`Integer`。自动装箱与拆箱可以简化代码,但也会引入一些问题,例如在循环中使用`Integer`而非`int`可能会导致内存泄漏。 2. **变量...

    Java 一些值得注意的细节

    1. **自动装箱与拆箱**:Java中的`Integer`等包装类提供了自动装箱和拆箱功能,方便了开发者操作。但需要注意,虽然在基本类型和包装类之间可以直接转换,但它们并不共享同一个缓存池,可能导致不必要的对象创建,...

    More.Java.Pitfalls中文版

    1. **类型转换错误**:Java中的自动装箱和拆箱可能导致类型转换异常,尤其是在涉及原始类型和包装类的操作时。书中可能讲解如何正确处理这类情况。 2. **空指针异常(NullPointerException)**:这是Java中最常见的...

    那些丑陋的Java API

    2. **Java中的陷阱与陷阱**: - `null`值在Java中是一个特殊的概念,但也是许多陷阱的来源。比如,未检查的空指针异常(NullPointerException)常常由对`null`对象的调用引发,这要求开发者时刻注意对象是否为空。 ...

    Java 面试中的陷阱

    11. **short变量加法**:`s1 = s1 + 1`是错误的,因为这会导致自动装箱拆箱,可能导致类型不匹配异常;而`s1 += 1`是正确的,因为这是复合赋值操作符,会自动处理类型转换。 12. **sleep() 和 wait()**:`sleep()`...

    Java puzzlers(java 解惑)附源码

    例如,puzzler之一可能涉及自动装箱和拆箱,当Integer对象与int基本类型进行操作时,如果不理解它们之间的关系,可能会出现意料之外的结果。源码中可能包含这样的例子,展示了如何正确处理这种情况,避免隐式转换...

    圣思园java视屏

    - **自动装箱与拆箱**:Java提供了自动装箱(primitive to wrapper)和拆箱(wrapper to primitive)的功能,需要注意装箱后的对象引用可能会带来的性能影响。 - **溢出问题**:对于有符号的整数类型,当数值超过...

    <好书>java解惑(java puzzlers),过来挑战吧

    1. 类型转换:Java是一种静态类型语言,但类型转换时可能出现问题,如自动装箱拆箱可能导致的意外行为,或者是不恰当的强制类型转换导致的ClassCastException。 2. 对象引用:Java中的对象引用有时会让人迷惑,例如...

    Java OCA 考试指南带highlight

    - 正确理解和使用Java的装箱和拆箱机制。 - 深入理解Java内存模型,特别是在多线程环境下对变量的访问和修改。 考生在准备Java OCA考试时,应重点学习以上知识点,深入理解概念并能够解决实际编程问题。同时,参考...

    java-puzzlers源代码

    1. **类型转换和自动装箱拆箱**:Java中的基本类型与对应的包装类之间可以进行自动转换,但这种转换可能隐藏着一些潜在的问题,如精度丢失、隐式转型等。 2. **变量作用域**:Java中变量的作用域是严格控制的,包括...

Global site tag (gtag.js) - Google Analytics