Arrays类、基本类型、包装类的自动装箱和拆箱

本文深入讲解Java.util.Arrays类的功能和使用方法,包括数组赋值、排序、比较、查找及转换等操作,同时介绍基本数据类型与包装类的区别,以及String与int类型之间的转换方式。

Arrays类

java.util.Arrays 类能方便地操作数组,它提供的所有方法都是静态的。
具有以下功能:
1.给数组赋值:通过 fill 方法。
2.对数组排序:通过 sort 方法,按升序。
3.比较数组:通过 equals 方法比较数组中元素值是否相等。
4.查找数组元素:通过 binarySearch 方法能对排序好的数组进行二分查找法操作。

Arrays类的方法使用

join 将数组按照指定的分隔符拆分字符串,原有的数组不变
toString 将数组转化为字符串,原有的数组不变
sort 对指定对象数组根据其元素的自然顺序进行升序排列。同样的方法适用于所有的其他基本数据类型(Byte,short,Int等)。
revser 将数组倒过来排序,原来数组改变
indexOf / lastIndexOf 获取数组中某一项的索引,通常用来检测数组中是否包含某一项内容,不包含返回的是-1
forEach 循环数组中每一项,然后进行相关的操作
length 返回数组的长度

基本数据类型

这种类型是通过诸如 int a=7; 的形式来定义的,称为自动变量。这里自动变量是字面值。不是类的实例,即不是类的引用,这里并没有类的存在。a 是指向一个 int 类型的引用,指向 7 这个字面值。由于其大小确定生存期可知(这些定义在某个程序块中,程序块退出后,字段值就消失),因此存在栈中.
由于栈的数据可以共享,因此 int a=3; int b=3; 这段代码,编译器首先处理 int a =3; ,先会在栈中创建一个变量为 a 的引用,然后查找有没有字面值为 3的地址,没有找到,就开辟一个存放 3 这个字面值的地址,然后将a 指向 3 的地址。接下来处理int b =3; 在创建完 b 这个引用变量后,由于栈中已经有 3 这个字面值,便将 b 指向 3 的地址。【定义变量,给变量赋值】

包装类

Java中的基本类型不是面向对象的,它们只是纯粹的数据,除了数值本身的信息之外,基本类型数据不带有其他信息或者可操作方法。这在实际使用中存在很多不足,为了解决这个不足,java就针对每一种基本数据类型提供了对应的包装类类型。

基本类型大小包装类
boolean/Boolean
char16bitCharacter
byte8bitByte
short16bitShort
int32bitInteger
long64bitLong
float32bitFloat
double64bitDouble

拆箱,装箱
装箱:根据数据创建对应的包装对象。
Integer i = new Integer (3);
Integer j = 4;//jdk1.5 之后可以通过这种方式自动装箱
拆箱:将包装类型转换为基本数据类型。
int index2 = j.intValue();
int index1 = i;//自动拆箱

在自动装箱过程时,编译器调用的是static Integer valueOf(int i)这个方法 于是Integer a=3; ==> Integer a=Integer.valueOf(3);。
此方法与new Integer(i)的不同处在于:
方法一调用类方法返回一个表示 指定的 int 值的 Integer 实例。方法二产生一个新的Integer 对象。

缓冲机制

JDK API文档中对这个新的valueOf方法有明确的解释:
如果不需要新的 Integer 实例,则通常应优先使用该方法,而不是构造方法 Integer(int),因为该方法有可能通过缓存经常请求的值而显著提高空间和时间性能 .

查看Integer的valueOf方法的:

public static Integer valueOf(int i) {
    assert IntegerCache.high >= 127;
    //static final int low = -128;
    //当-128=<i<=127的时候,就直接在缓存中取出 i de  Integer 类型对象
    if (i >= IntegerCache.low && i <= IntegerCache.high)
        return IntegerCache.cache[i + (-IntegerCache.low)];
    //否则就在堆内存中创建
    return new Integer(i);
}

IntegerCache初始化后内存中就有Integer缓冲区cache[]了,-128~127区间的int值有其对应的的包装对象。
Integer k=Integer.valueOf(1); 与Integer j=1; 本质上相同,指向缓冲池中同一对象。包装对象与数值比较,自动拆箱。
而对于大于127 的数值,执行的都是return new Integer(i) 都在堆内存中,但是地址不同。

String和int类型的相互转换

int – String
a:和""进行拼接
b:public static String valueOf(int i)
c:int – Integer – String
d:public static String toString(int i)

String – int
a:String – Integer – intValue();
b:public static int parseInt(String s)

<think>我们正在讨论Java中的自动装箱拆箱,特别是在List<Integer>的上下文中。根据用户的问题,我们需要解释自动装箱拆箱的原理以及使用方法,并结合提供的引用材料。 首先,自动装箱(Autoboxing)是指将基本数据类型自动转换为对应的包装对象,而自动拆箱(Unboxing)则是将包装对象自动转换为基本数据类型。这在Java中是为了方便在需要对象的地方使用基本数据类型,例如在集合中(因为集合只能存储对象,不能存储基本数据类型)。 在List<Integer>中,当我们添加一个int基本类型时,Java会自动将其装箱为Integer对象;当我们从列表中取出Integer对象并赋值给int基本类型时,会自动拆箱。 引用[1]中的代码示例: ```java List<Integer> list = Arrays.asList(1,2,3,4); int sum = 0; for(int i:list) sum +=i; ``` 这里,`Arrays.asList(1,2,3,4)`中的每个整数都会被自动装箱为Integer对象。在for-each循环中,每次迭代将Integer对象从列表中取出,然后自动拆箱为int类型,以便进行累加。 原理: - 自动装箱:当我们将基本数据类型传递给需要对象的方法或赋值给对象引用时,编译器会自动调用对应包装的valueOf方法(例如Integer.valueOf(int))来创建对象。 - 自动拆箱:当我们需要将包装对象转换为基本数据类型时,编译器会自动调用对应包装的xxxValue方法(例如Integer.intValue())来获取基本数据类型的值。 引用[2][3]提到了自动装箱拆箱的一些陷阱: 1. 包装对象的比较:使用`==`比较两个包装对象时,比较的是对象的地址。对于Integer,在-128到127之间的整数,由于IntegerCache的存在,会返回缓存的对象,因此在这个范围内的相同整数使用`==`比较会返回true,超出这个范围则返回false(因为每次装箱都会创建新的对象)。所以,在比较包装对象时,应该使用equals方法。 2. 在遇到算术运算时,包装对象会自动拆箱。例如,在表达式`c == (a + b)`中,ab会先拆箱,然后相加,再与c拆箱后的值比较(数值比较)。 3. 包装的equals方法不会处理类型转换。例如,在`g.equals(a+b)`中,a+b是int类型,然后被装箱为Integer,而g是Long类型,所以equals方法会先检查类型类型不同直接返回false。 使用方法: - 在集合中使用基本数据类型包装(如List<Integer>)时,可以像使用基本数据类型一样进行添加获取,自动装箱拆箱会隐式进行。 - 但要注意比较操作,应使用equals方法而不是`==`。 - 注意在混合类型表达式中(如LongInteger一起运算),会自动拆箱基本类型进行运算,但重新赋值给包装时要注意类型。 现在,我们结合用户的问题,给出一个清晰的解释示例。 用户问题:理解Java中List<Integer>的自动装箱自动拆箱机制,包括原理及使用方法。 回答结构: 1. 解释自动装箱拆箱的概念。 2. 说明在List<Integer>中的具体表现。 3. 给出示例代码并解释。 4. 指出注意事项(陷阱)。 同时,根据指令,我们需要生成相关问题。 参考引用: [^1] 展示了自动装箱拆箱在List<Integer>中的使用。 [^2] 详细说明了自动装箱拆箱的陷阱。 [^3] 提到类型擦除自动装箱是语法糖。 [^4] 提到了包装的一些属性集合的使用。 因此,我们可以这样组织回答:</think>### Java List<Integer> 自动装箱拆箱机制详解 #### 一、核心原理 1. **自动装箱(Autoboxing)** 当基本数据类型(如 `int`)需要作为对象(如 `Integer`)使用时,编译器自动将基本类型转换为对应的包装对象: ```java List<Integer> list = new ArrayList<>(); list.add(5); // 等价于 list.add(Integer.valueOf(5)); ``` 此处 `int` 值 `5` 被自动装箱为 `Integer` 对象[^1][^3]。 2. **自动拆箱(Unboxing)** 当包装对象需要作为基本类型使用时,编译器自动将包装对象转换为基本类型: ```java int first = list.get(0); // 等价于 int first = list.get(0).intValue(); ``` 从 `List<Integer>` 获取元素时自动拆箱为 `int`[^1][^3]。 #### 二、在 List<Integer> 中的工作流程 ```java List<Integer> numbers = Arrays.asList(10, 20, 30); // 自动装箱:int → Integer int sum = 0; for (int num : numbers) { // 循环中自动拆箱:Integer → int sum += num; // 直接使用基本类型运算 } ``` - **添加元素**:所有 `int` 值自动装箱为 `Integer` 对象存储 - **遍历操作**:迭代时自动拆箱为 `int`,支持基本类型运算[^1][^4] #### 三、关键注意事项 1. **性能影响** 频繁装箱/拆箱会产生额外对象开销(如循环内操作),可能影响性能: ```java // 低效示例:循环中重复装箱 for (int i = 0; i < 10000; i++) { list.add(i); // 每次循环都新建 Integer 对象 } ``` 2. **对象比较陷阱** 包装对象比较需使用 `equals()` 而非 `==`: ```java Integer a = 200; Integer b = 200; System.out.println(a == b); // false(对象地址不同) System.out.println(a.equals(b)); // true(值相同) ``` 注意 `Integer` 缓存范围:`-128~127` 会复用对象[^2]。 3. **空指针风险** 自动拆箱时若对象为 `null` 会抛出异常: ```java List<Integer> list = new ArrayList<>(); list.add(null); int num = list.get(0); // 抛出 NullPointerException ``` #### 四、最佳实践建议 1. 在集合操作中直接使用 `Integer` 避免频繁转换: ```java // 推荐:减少拆箱次数 Integer sum = list.stream().reduce(0, Integer::sum); ``` 2. 比较数值时显式拆箱: ```java if (num1.intValue() == num2.intValue()) { ... } ``` 3. 批量操作优先使用基本类型数组: ```java int[] primitiveArray = list.stream().mapToInt(Integer::intValue).toArray(); ``` #### 五、底层实现机制 - 编译时通过语法糖实现,字节码中插入 `Integer.valueOf()` `intValue()` 调用[^3] - 泛型擦除后 `List<Integer>` 实际存储 `Object` 类型装箱确保类型安全[^3] > 自动装箱/拆箱是编译器提供的语法糖,本质是编译器自动插入包装/解包方法调用[^3]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值