关于java装箱和拆箱

本文介绍了Java装箱和拆箱的转换方式,如Integer a = 100 会转换为 Integer a = Integer.valueof(100) 。还提到Java基本类型包装类大多实现常量池技术,Byte、Short等有对应范围缓存数据,Float、Double未实现。同时说明了“==”运算符在不同操作数情况下的比较规则。

关于java装箱和拆箱

转载http://www.cnblogs.com/dolphin0520/p/3780005.html

 

Integer a = 100 ==>   Integer a = Integer.valueof(100)

int n = a            ==> n = Integer.intvalue(a)  变为数值

Java 基本类型的包装类的大部分都实现了常量池技术,即 Byte,Short,Integer,Long,Character,Boolean;前面 4 种包装类默认创建了数值[-128,127] 的相应类型的缓存数据,Character创建了数值在[0,127]范围的缓存数据,Boolean 直接返回True Or False。如果超出对应范围仍然会去创建新的对象。

 Integer i1 = 100;  Integer i2 = 100;  System.out.println(i1==i2);  true

Integer i3 = 100;  Integer i4 = 100;  System.out.println(i3==i4);  false  因为超出常量池,创建new Integer(i)

Float,Double 并没有实现常量池技术  他们的比较都是false

当 "=="运算符的两个操作数都是 包装器类型的引用,则是比较指向的是否是同一个对象,而如果其中有一个操作数是表达式(即包含算术运算)则比较的是数值(即会触发自动拆箱的过程)

 

 

<think>首先,用户的问题是基于之前的引用内容,询问Java装箱拆箱的原理、使用方法及示例。系统指令要求我用中文回答,结构清晰,逐步解决问题,并保证真实可靠。引用来自多个来源,我需要整合这些信息。 关键点从引用中提取: - 引用[1]:装箱通过调用包装器的valueOf方法实现,拆箱通过调用包装器的xxxValue方法实现。示例代码展示了手动自动装箱拆箱。 - 引用[2]:装箱调用Integer.valueOf(int),拆箱调用Integer.intValue()。问题示例展示了Integer缓存范围(-128到127)导致的行为差异。 - 引用[3]:自动装箱是将基本数据类型自动转换为包装器类型,原理涉及valueOf方法。 - 引用[4]:自动装箱是自动将基本数据类型转成包装器类型(如Integer.valueOf),拆箱是自动将包装器类型转成基本数据类型(如Integer.intValue)。 - 引用[5]:自动装箱拆箱的反汇编示例,显示底层调用valueOfintValue方法。 核心原理: - **装箱**:将基本类型(如int)转换为包装器类型(如Integer)。在Java中,自动装箱时调用包装类的静态方法valueOf(例如Integer.valueOf)。 - **拆箱**:将包装器类型转换回基本类型。自动拆箱时调用实例方法如xxxValue(例如Integer.intValue)。 - **Integer缓存**:Java为Integer缓存了小范围值(-128到127),所以在这个范围内使用valueOf可能返回相同的对象,出范围则创建新对象。这解释了为什么比较引用时会显示不同结果。 使用方法: - 自动装箱:直接赋值基本类型给包装器变量,如 `Integer i = 100;`,等价于 `Integer i = Integer.valueOf(100);` - 自动拆箱:使用包装器变量在需要基本类型的上下文中,如 `int j = i;`,等价于 `int j = i.intValue();` - 手动方式:也可以显式调用方法,但自动机制简化了代码。 示例: - 从引用中提取或创建简单示例,展示装箱拆箱缓存效果。 - 示例代码可以用Markdown格式呈现,引用相关部分。 回答结构: 1. **引言**:简要解释装箱拆箱是什么。 2. **原理**:详细说明valueOfxxxValue方法的作用,以及Integer缓存机制。 3. **使用方法**:描述自动装箱拆箱的语法。 4. **示例**:提供代码示例,包括手动自动方式,以及缓存问题。 5. **生成相关问题**:按照系统指令,在结束时生成相关问题。 系统指令要求: - 行内数学表达式用$...$,但这里可能不需要,因为是Java代码叙述。 - 独立公式用$$...$$,但Java不需要公式。 - LaTeX语法正确,但Java代码用代码块。 - 使用中文回答。 - 生成相关问题。 - 引用段落末尾添加引用标识,如[^1]。从引用看,需要标注来源,但用户提供了引用索引,我可以对应使用,如[^1]、[^2]等。 - 回答中引用的内容末尾添加引用标识。 相关问题生成: - 在结束时,基于主题生成2-3个问题,例如缓存范围、性能影响、常见陷阱。 最终回答结构: - 清晰分段: - 什么是装箱拆箱? - 原理(valueOf方法、缓存机制)。 - 使用方法(自动手动)。 - 示例代码。 - 注意事项(如缓存导致的引用比较问题)。 - 结束部分:生成相关问题。 确保真实可靠:基于Java标准知识,这些原理是正确的。 </think>### Java装箱拆箱的原理、使用方法及示例 Java中的装箱(boxing)拆箱(unboxing)是自动类型转换机制,用于简化基本数据类型(如`int`、`double`)与对应的包装器类(如`Integer`、`Double`)之间的转换。下面我将从原理、使用方法示例三个方面逐步解释,确保内容真实可靠,基于Java官方文档常见实践[^1][^2][^3][^4][^5]。 #### 1. **原理** 装箱拆箱的底层实现依赖于Java编译器的自动优化,涉及包装器类的特定方法: - **装箱(Boxing)**:当将一个基本类型赋值给包装器对象时,编译器自动调用包装器的`valueOf()`方法。例如,`Integer i = 100;` 会被编译为 `Integer i = Integer.valueOf(100);`。这个方法返回一个新对象,但Java为某些包装器(如`Integer`)缓存了小范围值(-128到127),以提高性能[^1][^2][^4]。 - **拆箱(Unboxing)**:当在需要基本类型的上下文中使用包装器对象时,编译器自动调用包装器的`xxxValue()`方法(如`intValue()`)。例如,`int j = i;` 会被编译为 `int j = i.intValue();`。这直接提取包装器对象中的基本值[^1][^2][^5]。 关键原理点: - **自动机制**:Java 5及以上版本支持自动装箱拆箱,编译器在编译时插入`valueOf``xxxValue`调用,无需手动编写[^3][^4]。 - **Integer缓存**:对于`Integer`类,`valueOf()`方法缓存了-128到127的值(通过静态内部类实现),这意味着范围内的值可能返回相同对象引用,范围外则创建新对象。这会影响引用比较(`==`),但值比较(`equals()`)不受影响[^2][^4]。 - **性能考虑**:自动装箱拆箱简化代码,但频繁操作可能产生额外对象开销(如在大循环中),需警惕性能影响[^1][^5]。 #### 2. **使用方法** 装箱拆箱的语法简单直观,可以通过自动或手动方式实现: - **自动方式**:编译器隐式处理转换,适用于大多数场景。 - **装箱语法**:`包装器类 变量 = 基本类型值;`(例如 `Integer num = 42;`)。 - **拆箱语法**:`基本类型 变量 = 包装器对象;`(例如 `int k = num;`)。 - **手动方式**:显式调用方法,适用于需要控制或调试的场景。 - **装箱语法**:`包装器类 变量 = 包装器类.valueOf(基本类型值);`(例如 `Integer num = Integer.valueOf(42);`)。 - **拆箱语法**:`基本类型 变量 = 包装器对象.xxxValue();`(例如 `int k = num.intValue();`)。 使用注意事项: - **适用范围**:所有基本类型都有对应的包装器类(如`Integer`、`Double`、`Character`),方法类似。 - **缓存行为**:仅在`Integer`、`Short`、`Byte`等包装器中存在缓存,使用时注意引用比较问题[^2][^4]。 - **Null处理**:拆箱包装器对象为`null`时会抛出`NullPointerException`,需确保对象非空[^3][^5]。 #### 3. **示例** 以下代码示例展示装箱拆箱的自动手动实现,以及缓存机制的影响。示例基于引用中的代码,并加以注释说明。 ```java // 示例1: 基本自动装箱拆箱 public class AutoBoxingExample { public static void main(String[] args) { // 自动装箱: 编译器调用 Integer.valueOf(100) Integer i = 100; // 等价于 Integer i = Integer.valueOf(100); // 自动拆箱: 编译器调用 i.intValue() int j = i; // 等价于 int j = i.intValue(); System.out.println(j); // 输出: 100 // 自动拆箱装箱: 表达式操作 i += 50; // 等价于 i = Integer.valueOf(i.intValue() + 50); System.out.println(i); // 输出: 150 } } ``` ```java // 示例2: 手动装箱拆箱对比 public class ManualBoxingExample { public static void main(String[] args) { // 手动装箱: 显式调用 valueOf Integer a = Integer.valueOf(200); // 手动拆箱: 显式调用 intValue int b = a.intValue(); System.out.println(b); // 输出: 200 // 混合操作 a = Integer.valueOf(a.intValue() + 100); // 手动拆箱装箱 System.out.println(a); // 输出: 300 } } ``` ```java // 示例3: Integer缓存机制演示 public class CacheExample { public static void main(String[] args) { Integer x1 = 100; // 自动装箱,调用 valueOf(100),在缓存范围内 Integer x2 = 100; // 同样在缓存范围内,可能返回相同对象 System.out.println(x1 == x2); // 输出 true,因为引用相同 Integer y1 = 200; // 自动装箱,调用 valueOf(200),出缓存范围 Integer y2 = 200; // 新对象创建 System.out.println(y1 == y2); // 输出 false,引用不同 // 值比较不受影响 System.out.println(y1.equals(y2)); // 输出 true } } ``` **解释**: - 示例1展示了自动机制的简便性:`i += 50` 隐式执行拆箱装箱。 - 示例2对比手动方式,强调显式调用方法。 - 示例3揭示了缓存风险:范围内值(如100)比较引用时为`true`,范围外(如200)为`false`,但`equals()`方法始终基于值比较[^2][^4]。 #### 注意事项 - **性能优化**:避免在循环中频繁装箱拆箱,以减少对象创建开销[^1][^5]。 - **类型安全**:自动机制可能掩盖类型错误,如混合不同包装器类型会导致编译失败。 - **缓存范围**:Java规范规定`Integer`缓存为-128到127,但可通过JVM参数调整上限[^2][^4]。 通过以上内容,您应能理解Java装箱拆箱的核心原理实际应用。如果需要更深入细节,如反汇编验证或性能测试,可参考Java开发工具(如javap命令)。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值