java中的Boxing和unboxing

本文探讨了Java面试中关于Integer对象比较的问题,解释了为何在特定数值范围内Integer对象的比较会返回true,而超出该范围则返回false。文章还介绍了Java 5引入的Boxing和unboxing特性,并给出了代码示例。

邢红瑞 发表于 2007-6-8 16:00:58

最近给替一个朋友出的几道java的面试题,主要是面试java高级工程师,报酬就是晚饭,已经沦落的卖艺的境地。
题目很简单
   Integer i1 = 100;
   Integer i2 = 100;
   Integer i3 = 1000;
   Integer i4 = 1000;
   System.out.println(i1==i2);
   System.out.println(i3==i4);
很遗憾,没有一个答对的,正确答案是
true
false
如果面试者写这样的写是错误的,就算通过。
这个的原因要从java5的Boxing和unboxing谈起,boxing就是封装基本类型的对象,unboxing就是转换对象到基本类型。
Integer, Long, Float, Double, Short, Character etc.都是这样的类型他们是immutable。
Boxing
在jdk1.4.2中,
必须是// Assigning primitive type to wrapper type
   Integer iWrapper = new Integer(10);
java5中
 // Assigning primitive type to wrapper type
   Integer iWrapper = 10;
unboxing
在jdk1.4.2中,
int iPrimitive = iWrapper.intValue();
java5中
int iPrimitive = iWrapper;
下面是基本类型作为对象存储的范围,
boolean values true and false
All byte values
short values between -128 and 127
int values between -128 and 127
char in the range \u0000 to \u007F
如果int values between -128 and 127,VM使用相同的对象,否则创建新的对象。
所以这段代码,大家不要奇怪
System.out.println(0L == 0);
System.out.println(((Long)0L).equals(0));
第二行代码是0不等于0
因为大家犯这样的一个错误
 static private final String LOCK = "LOCK";
  void testMethod() {
    synchronized(LOCK) {
    ...
    }
  }
应该用new,不要直接=,对于int,最好使用int a[0] ,因为array也是对象,不像Integer,a[0]的值可以改变。

123733.html

坏男孩 2007-06-12 22:39 发表评论
<think>嗯,用户想了解Java中的装箱拆箱的详细机制原理。首先,我需要回忆一下自己对这个主题的理解。装箱拆箱是Java中的自动转换机制,把基本类型对应的包装类相互转换。比如int转Integer是装箱,反过来就是拆箱。用户可能已经知道基本类型包装类的存在,但具体是怎么自动转换的,底层原理是什么,可能还不清楚。 接下来,我需要整理一下相关的知识点。根据提供的引用内容,装箱拆箱主要涉及到集合的使用,比如List<Integer>这样的集合存储int数据时会自动装箱。自动装箱在Java 5引入,编译时自动插入转换代码。比如Integer i = 100;实际上编译时会变成Integer.valueOf(100)。而拆箱则是调用intValue()之类的方法。 然后要考虑用户可能存在的疑问点。比如自动装箱的性能问题,因为频繁的装箱拆箱会产生额外的对象,影响性能,尤其是在循环中。还有缓存机制,比如Integer的-128到127之间的值会被缓存,这可能导致一些意想不到的结果。比如两个Integer对象用==比较时,在这个范围内的可能相等,之外的则不会,因为对象地址不同。 用户可能还想知道如何避免常见的坑,比如空指针异常,当拆箱一个null的包装类对象时会抛出NPE。另外,隐式转换的规则,比如在方法重载时选择哪个方法,比如一个方法有intInteger的重载版本,自动装箱会影响调用的方法。 需要结合引用中的资料,特别是引用4提到的自动装箱拆箱的实现原理,以及引用2中的性能分析常见坑点。还要注意语法细节,比如valueOfxxxValue方法的作用,以及编译后的字节码如何实现这些转换。 此外,用户可能对实际应用场景感兴趣,比如集合类使用时的自动装箱,或者在泛型中必须使用包装类的情况。同时,面试中常问的问题,比如缓存机制、性能优化建议,也需要涵盖进去。 在组织回答时,需要分点清晰,先解释概念,再讲实现原理,然后讨论性能影响,最后给出常见问题优化建议。同时,要使用用户提供的引用资料来支持内容,并在适当的位置添加引用标识。 需要注意的是,用户提供的引用中有重复的内容,比如引用1、3、4都提到装箱拆箱的基本概念,而引用2则更深入讨论原理、性能坑点。需要整合这些信息,避免重复,同时确保覆盖所有关键点。 可能还需要举例说明,比如代码示例展示自动装箱拆箱的情况,以及缓存机制的例子。比如Integer a = 100; Integer b = 100; a==b为true,而Integer c=200; Integer d=200; c==d为false,这样能直观展示缓存的影响。 另外,要提醒用户注意自动拆箱时的空指针异常,比如Integer num = null; int n = num; 这会导致运行时错误。这是常见的问题,需要特别指出。 最后,生成的相关问题需要围绕用户可能进一步想了解的内容,比如原理如何实现、性能影响、应用场景、常见错误等。</think>### Java 装箱与拆箱原理及实现详解 #### 一、基本概念 **装箱**(Boxing)是将基本数据类型(如`int`、`double`)自动转换为对应的包装类(如`Integer`、`Double`)的过程;**拆箱**(Unboxing)则是反向操作。这一机制自Java 5引入,简化了基本类型与对象类型之间的转换[^3][^4]。 例如: ```java Integer boxed = 42; // 自动装箱:等价于 Integer.valueOf(42) int unboxed = boxed; // 自动拆箱:等价于 boxed.intValue() ``` #### 二、实现原理 1. **编译阶段插入代码** 编译器会自动插入`Integer.valueOf()`(装箱)或`intValue()`(拆箱)等方法调用。例如: ```java // 源码 Integer num = 100; // 编译后实际代码 Integer num = Integer.valueOf(100); ``` 2. **缓存机制优化** 包装类(如`Integer`)对特定范围的值(默认`-128`至`127`)进行缓存[^4]: ```java Integer a = 127; Integer b = 127; System.out.println(a == b); // true(同一缓存对象) Integer c = 200; Integer d = 200; System.out.println(c == d); // false(新建对象) ``` 3. **拆箱潜在风险** 若包装类对象为`null`,拆箱会触发`NullPointerException`: ```java Integer num = null; int n = num; // 运行时抛出异常 ``` #### 三、性能影响 - **对象创建开销**:频繁装箱会生成大量临时对象,增加GC压力。 - **计算效率对比**: ```java Long sum = 0L; // 每次循环触发装箱(性能差) for (long i = 0; i < N; i++) sum += i; long sum = 0L; // 直接使用基本类型(高效) for (long i = 0; i < N; i++) sum += i; ``` 前者因循环中重复装箱导致性能显著下降[^2]。 #### 四、应用场景与优化建议 1. **必用场景** - 集合类存储:如`List<Integer>`必须使用包装类型。 - 泛型参数:泛型仅支持对象类型。 2. **优化建议** - 优先使用基本类型,避免不必要的装箱。 - 谨慎处理包装类的`null`值,可用`Optional`类封装。 - 在循环或高频代码中减少自动装箱操作[^4]。 #### 五、常见问题 1. **方法重载优先级** ```java void test(int x) {} // 方法1 void test(Integer x) {} // 方法2 test(100); // 调用方法1(优先匹配基本类型) ``` 2. **`equals`与`==`的差异** ```java Integer a = 200; Integer b = 200; System.out.println(a == b); // false(比较对象地址) System.out.println(a.equals(b)); // true(比较值) ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值