public class Test {
public static void main(String[] args) {
//为什么要有包装类: java说自己是万物皆对象,基本数据类型不能有对象属性,基本数据类型不能方法的调用
//byte ------------> Byte
//short ------------> Short
//int ------------> Integer
//long ------------> Long
//float ------------> Float
//double ------------> Double
//char ------------> Character
//boolean ------------> Boolean
Integer i = 127; // Integer i = Integer.valueOf(127);
Integer j = 127; // Integer j = Integer.valueOf(127);
System.out.println(i == j); // True
Integer k = 128;
Integer l = 128;
System.out.println(k == l); //False
//面试点: 128陷阱
//总结:我们使用Integer定义的数据会进行自动装箱,自动装箱调用valueOf()方法,该方法会判断我们的入参是否在-128-127之间,如果在这个之间
// 则会返回一个已经存在的对象的地址(该对象在Catch数组当中,Catch数组是一个从-128-127的数组),不会重新创建对象,否则会重新创建对象
//包装类的自动拆装箱 :因为有自动拆装箱的存在,所以包装类定义的数据和基本数据类型可以相互转换
// Integer m = 10; //自动装箱 Integer m = Integer.valueOf(10);
Integer m = Integer.valueOf(10);
int a = m; //自动拆箱 int a = m.intValue();
}
}
一、 包装类的核心作用
Java 号称 “万物皆对象”,但基本数据类型(如 int、double 等)不具备对象的属性和方法调用能力。包装类为每种基本数据类型提供了对应的 “对象化” 类(如Integer对应int),使其能参与面向对象操作(如泛型、集合存储等)。
二、基本数据类型与包装类的映射
| 基本数据类型 | 包装类 |
|---|---|
| byte | Byte |
| short | Short |
| int | Integer |
| long | Long |
| float | Float |
| double | Double |
| char | Character |
| boolean |
Boolean |
三、 自动装箱与拆箱
- 自动装箱:基本数据类型自动转换为对应包装类对象的过程。例如
Integer i = 127;底层执行Integer.valueOf(127)。 - 自动拆箱:包装类对象自动转换为对应基本数据类型的过程。例如
int a = m;底层执行m.intValue()。
四、 Integer 的 “128 陷阱”(面试重点)
Integer.valueOf() 方法在处理 -128~127 范围内的整数时,会直接返回常量池(Cache 数组[-128~127])中已存在的对象引用;若超出该范围,则会新建对象。
- 案例 1:
Integer i = 127; Integer j = 127;→i == j结果为true(二者指向常量池同一对象)。 - 案例 2:
Integer k = 128; Integer l = 128;→k == l结果为false(二者是不同对象)。
1. 代码与机制解析
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
- 逻辑:判断整数
i是否在IntegerCache的默认范围(-128~127)内。若在范围内,返回缓存中已有的对象引用;否则新建Integer对象。
2. IntegerCache 缓存与 “128 陷阱”
| 场景 | 内存表现 | ==结果 |
|---|---|---|
i = 127 | Integer i和Integer j均指向IntegerCache中同一对象(如图示i和j引用地址均为0x127) | true |
i = 128 | 超出缓存范围,Integer k和Integer l分别新建对象(图示k引用0xac,l引用0xcd) | false |

五、==与equals()练习与分析
public class Demo {
/**
* 自动装箱:基本数据类型------->包装类
* 自动拆箱:包装类--------->基本数据类型
* @param args
*/
public static void main(String[] args) {
int a = 10;
int b = 10;
Integer a1 = 10;
Integer b1 = 10;
Integer a2 = new Integer(10);
Integer b2 = new Integer(10);
System.out.println(a == b); //T 基本数据类型==比较值是否相等
System.out.println(a1 == b1); //T 128陷阱
System.out.println(a2 == b2); //F 创建两个不同新的对象
System.out.println(a1 == a); //T 这里Integer类型的a1会自动拆箱,转换成int类型 基本数据类型==比较值是否相等
System.out.println(a1.equals(a)); //T 这里Integer类型的a1会自动拆箱,转换成int类型 基本数据类型==比较值是否相等
System.out.println(a1 == a2); //F 两个Integer对象,两个对象地址不同
System.out.println(a == a2); //T 自动拆箱
}
}
1.== 比较规则与场景分析
==在基本数据类型当中比较值是否相同,在引用数据类型当中比较地址是否相同。
| 比较场景 | 比较规则 | 结果 | 原理说明 |
|---|---|---|---|
int a == int b | 基本数据类型比较 “值是否相等” | T | 10 和 10 值相等 |
Integer a1 == Integer b1(值在 - 128~127) | 引用类型比较 “地址是否相同”,因缓存复用地址 | T | 10 在IntegerCache缓存范围内,a1和b1指向同一缓存对象 |
Integer a2 == Integer b2(new创建) | 引用类型比较 “地址是否相同” | F | new会新建对象,a2和b2是不同对象 |
Integer a1 == int a | 自动拆箱后比较 “值是否相等” | T | a1自动拆箱为int,与a的值(10)比较 |
Integer a1 == Integer a2(缓存对象 vs new对象) | 引用类型比较 “地址是否相同” | F | a1是缓存对象,a2是新对象,地址不同 |
int a == Integer a2 | 自动拆箱后比较 “值是否相等” | T | a2自动拆箱为int,与a的值(10)比较 |
2.equals() 方法分析
//equals()不能在基本数据类型当中使用,在Object类当中的equals()方法用的是==比较地址
//String类重写了equals(),首先使用==比较地址,如果不相同则再去判断值是否相同。
Integer的equals()方法重写的目的是判断 “值是否相等”
Integer的equals()方法会先将参数自动拆箱为int,再比较值是否相等。因此 a1.equals(a) 结果为T(a1拆箱后值为 10,与a的值 10 相等)。
884

被折叠的 条评论
为什么被折叠?



