包装类
为什么要有包装类
Java 里8 种基本数据类型
(byte/short/int/long/float/double/char/boolean)不是对象,不继承Object。但是集合、泛型只能存对象,不能直接放基本类型,所以 Java 为每个基本类型提供了对应的包装类,把基本值包装成对象。
大部分就是首字母大写;只有两个特殊:
int → Integer
char → Character自动装箱 自动拆箱
装箱:基本类型 → 包装对象
Integer a = 10; // 自动装箱,等价于 Integer a = Integer.valueOf(10);- 拆箱:包装对象 → 基本类型
int b = a; // 自动拆箱,等价于 int b = a.intValue();Integer 缓存池
Integer.valueOf()会缓存-128 ~ 127的 Integer 对象,这个区间内直接复用对象,超出区间新建对象:Integer i1 = 100; Integer i2 = 100; System.out.println(i1 == i2); // true,在缓存池里 Integer i3 = 200; Integer i4 = 200; System.out.println(i3 == i4); // false,超出缓存,是两个不同对象包装类比较值,优先用
.equals(),不要用==包装类的常用作用
- 放入泛型、集合(
List<Integer>,不能写List<int>)- 可以存
null(基本类型有默认值,不能为 null)- 自带很多工具方法:字符串转数字、进制转换等
int num = Integer.parseInt("123"); // 字符串转int String s = Integer.toString(456); // 数字转字符串
装箱,拆箱
装箱
// 手动装箱 int i=10; Integer ii=Integer.valueOf(i)装箱:把基本类型 int,包装成 Integer 对象
valueOf():优先从缓存池-128~127拿现成对象,节省内存// 方式2:new Integer(i) 【不推荐,Java9已经废弃】,每次都新建对象,不走缓存 Integer ij = new Integer(i);new Integer():强制创建新对象,哪怕值在缓存区间也不复用
- 拆箱
每个包装类都有对应的// 拆箱 :从Integer对象里取出里面的int值 int j=ii.intValue();xxxValue()方法:Integer→intValue()Double→doubleValue()Character→charValue()- 自动装箱、自动拆箱
// 自动装箱: 等价与 Integer a=Integer.valueOf(10) Integer a=10; // 自动拆箱:等价于 int b=a.intValue(); int b=a;写起来更简洁,编译之后本质还是上面的 valueOf() 和 intValue()
自动装箱只是语法糖,底层调用的就是 valueOf,这也是缓存池生效的前提- 重点对比
Integer i1=100; // 自动装箱 ---> valueOf(100) 缓存里拿 Integer i2=100; System.out.println(i1==i2); // true , 同一个缓存对象 Integer i3=200; // 自动装箱,----> valueOf(200) 超出缓存,新建对象 Integer i4=200; System.out.println(i3==i4); // false ,两个不同对象Integer 的缓存数组 cache 只预存了-128 ~ 127之间的对象。
坑点:
(a) == 比较的是对象地址;
(b)比较包装类的值,一定要用 .equals()
面试题
Integer a=127; Integer b=127; Integer c=128; Integer d=128; System.out.println(a==b); // true System.out.println(c==d); // false // equals 比较数值,不管是否在缓存区间 System.out.println(c.equals(d)); // true(1)Integer a = 127; Integer b = 127;
a) 这是自动装箱,底层等价于Integer.valueOf(127)。
b) Java 的Integer内部有一个静态缓存IntegerCache,
默认缓存范围是-128 ~ 127。
b) 数字 127 落在缓存区间内,valueOf直接返回缓存里同一个对象。
d)==对引用类型比较的是对象内存地址,a和b地址相同,所以输出true。
(2)Integer c = 128;、Integer d = 128;
a)128 超出了-128--127的缓存范围,Integer.valueOf(128)
会新建两个不同的 Integer 对象。
b)c和d是两个独立对象,内存地址不一样,==判断地址不相等,输出false。
(3)补充
a)==:基本类型比值;包装类(引用类型)比对象地址
b)比较包装类里面的数值大小,要用 a.equals(b)System.out.println(c.equals(d)); // true,比较内部数值
泛型
- 背景
普通类 / 方法只能写死固定类型(基本类型、自定义类),想一套代码适配多种类型就很麻烦,这就是泛型要解决的问题- 版本
泛型是JDK1.5新增语法- 通俗理解
泛型 =适用于很多类型- 专业定义
泛型本质是类型参数化:把类型像参数一样传入,让类、接口、方法可以在不修改源码的情况下,支持多种不同类型泛型带来的好处
- 编译期类型检查,减少类型转换异常
- 避免大量强制类型转换
- 复用一套代码,适配多种引用类型
- 泛型不支持基本类型,要用包装类(Integer 代替 int)