拆箱和装箱-性能测试

using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using UnityEngine;
using Debug = UnityEngine.Debug;

//装箱:值类型转换为引用类型
//拆箱:引用类型转换为值类型
//引用类型:任何称之为"类"的类型都是引用类型 使用class修饰 string object
//值类型:所有值类型都称为结构或枚举,使用struct或enum修饰 int float double char


public class Test : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
        int count = 100000000;
        Stopwatch t1=new Stopwatch();
        Stopwatch t2=new Stopwatch();
        Stopwatch t3=new Stopwatch();
        t1.Start();
        List<int>l=new List<int>();
        for (int i = 0; i < count; i++)
        {
            l.Add(i);//不发生装箱操作
            int x = l[i];//不发生拆箱操作
        }
        t1.Stop();
        Debug.Log("List time"+t1.ElapsedMilliseconds+"ms");
        
        t2.Start();
        ArrayList a=new ArrayList();
        for (int i = 0; i < count; i++)
        {
            a.Add(i);//发生装箱操作 int转为object 值类型转换为引用类型
            int b = (int)a[i];//发生拆箱操作 object(引用类型)强转为值类型(int)
        }
        t2.Stop();
        Debug.Log("ArrayList time"+t2.ElapsedMilliseconds+"ms");

        t3.Start();
        ArrayList e=new ArrayList();
        for (int i = 0; i < count; i++)
        {
            e.Add("X");//不发生装箱操作            
            string f = e[i].ToString();//不发生拆箱操作        }
        t3.Stop();
        Debug.Log("ArrayList1 time"+t3.ElapsedMilliseconds+"ms");
    }
    //测试结果 List time1902ms  ArrayList time8187ms ArrayList1 time3547ms
    //数据表明 泛型数组有两个优势
    //1.对于存储值类型数据,性能更优
    //2.使代码更清晰和保证类型的安全 因为类型是声明的时候就指定
}
<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命令)。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值