学习目标
- 了解包装类是什么。
- 了解装箱和拆箱机制
- 自动装箱和自动拆箱
0.为什么要学习包装类?
在学习包装类之前,我们要了解包装类用来干什么?
前面提过的Java 8大数据类型(整型:byte ,short , int , long ;浮点型: float ,double;布尔类型:boolean ;字符型: char )。
- 在面向对象编程
- Java 中的包装类 (Wrapper Classes) 是为了解决基本数据类型(如 int, char, double 等)不能直接作为对象使用的问题。
- 为引入泛型和后续集合框架(Java数据结构) 打基础。比如列表,集合,映。Java中一切皆对象的理念,从设计的角度来看,对象的引用可以提供更多的灵活性和功能,比如可以内置更多的常量属性和便捷的方法。
- 前面1提过,这里具体说一下:由于包装类提供了许多实用的方法和属性,用于操作和处理基本数据类型。比如,valueOf方法,Integer类提供了将字符串转换为整数的方法,以及获取整数的最大值、最小值等属性。
- 支持null值:基本数据类型不支持null值,但在某些情况下,我们可能需要表示一个变量没有值。可以通过使用包装类,将引用设置为null来表示这种情况。
- Java泛型不支持基本数据类型。
一、包装类的定义概念
在Java中,基本类型不是类,为了在泛型代码中可以支持基本类型,Java给每个基本类型都对应了一个包装类型。
包装类。
int与char类型的包装类分别是Integer,Character。其余类型的包装类,类名是原基本数据类型关键字首字母大写。
包装类的使用
如果你不想关注包装类与基本数据类型内部的细节,你可以完全把包装类当成其基本数据类型使用。
包装类可以理解为升级版的基本数据类型,包装类与基本数据类型之间可以相互转换,且这种转换是自动的。
int a = 10;
Integer aObj = a;//等价Integer bObj = 20;
int b = bObj; //等价
关于泛型:
假设你要设计一个整型数组列表,ArrayList<int>
是错误的写法,<>是泛型的写法,<>内只能传类,而不能是基本数据类型。
var list = new ArrayList<Integer>()
,改成包装类就可以了。
二、包装类之间的继承关系
Java 中的包装类位于 java.lang 包中,并且它们都继承自 java.lang.Number 类(除了 Boolean 和 Character)。
具体包装类查阅文档
java.lang.Object├── java.lang.Number│ ├── java.lang.Byte│ ├── java.lang.Short│ ├── java.lang.Integer│ ├── java.lang.Long│ ├── java.lang.Float│ └── java.lang.Double├── java.lang.Character└── java.lang.Boolean
简单说明Number类,它是一个抽象类,Number类是所有包装类的父类(除了 Boolean 和 Character)。
Number类提供了将包装类转换为基本数据类型的方法,如intValue()、doubleValue()等。这些方法是由子类实现,作用是将包装类转化成对应的基本数据类型。
三、装箱与拆箱
int 与 Integer怎么转换呢?
Integer integer = new Integer(1)
,对于类实例化对象,你可能比较熟悉了。
但事实上只需Integer integer = 1;
Java底层设计,我们对于包装类不需要调用方法来手动转化,而是把它交给虚拟机操心。
先说明两个概念:
- 自动装箱:将基本数据类型转换为包装类。
- 自动拆箱:将包装类转换为基本数据类型。
Java虚拟机在运行时,会自动将基本数据类型转换为对应的包装类,这个过程称为自动装箱。同样地,Java虚拟机也会自动将包装类转换为基本数据类型,这个过程称为自动拆箱。
尝试一下手动装箱吧。
基本数据类型转包装类,采用的valueOf静态方法方法,而不是构造器(该方法已不推荐使用)。
int x = 10;
Integer y = Integer.valueOf(x);
包装类转基本数据类型,采用intValue()方法。
Integer x = 10;
int y = x.intValue();
//int y = (int)x; // 也可以类型转换写。
使用过程中,手动装箱和拆箱带来不少的代码量,所以为了减少开发者的负担,java 提供了自动机制。
我们没必要手动装箱和拆箱,java 虚拟机会自动帮我们完成,所以只是了解一些JVM在这个过程实际上帮我们调用了这些方法。## 包装类与基本数据类型的区别
你知道包装类是对象,基本数据类型是值。
但好像实际体验看包装类也可以完全充当基本数据类型啊。
```java
Integer a = 10;
Integer b = 10;
System.out.println(a == b); Integer c = 1000;
Integer d = 1000;
System.out.println(c == d);
输出结果:
true
false
为什么会出现这种情况呢?
这是因为Java在处理包装类时,有一个缓存机制。对于-128到127之间的整数,Java会缓存这些整数对应的包装类对象,当创建一个在这个范围内的整数包装类对象时,Java会直接返回缓存中的对象,而不是创建一个新的对象。这就是为什么a和b是相等的,因为它们引用的是同一个对象。而对于1000,Java不会缓存这个值对应的包装类对象,所以c和d引用的是不同的对象,所以它们不相等。
//java17,Integer类@IntrinsicCandidatepublic static Integer valueOf(int i) {if (i >= IntegerCache.low && i <= IntegerCache.high)return IntegerCache.cache[i + (-IntegerCache.low)];return new Integer(i);}
// IntegerCache是Integer类的一个内部类,它定义了两个静态变量low和high,分别表示缓存中最小值(-128)和最大值(127)。
static final Integer[] cache;
// cache数组用于存储缓存中的包装类对象,数组长度为256,即缓存了-128到127之间的整数对应的包装类对象。这些对象在静态区创建好了,这个范围内的数只需返回缓存中的对象即可,而不在这个范围内的数则直接创建新的对象。否则则要直接new一个对象。
结论:包装类是对象,符合缓存区的int数据,会让它们引用一个同一个静态区的对象,否则则创建新的对象。这就是上面true和false的原因。
遇事不决翻源码文档·和问ChatGpt。