基本类型与包装类
核心概念
Java提供了8种基本数据类型用于存储原始数据,同时为每种基本类型提供了对应的包装类,使其能参与面向对象编程。
一、8种基本数据类型
1.1 类型总览
| 分类 | 类型 | 字节 | 取值范围 | 默认值 |
|---|---|---|---|---|
| 整型 | byte | 1 | -128 ~ 127 | 0 |
| short | 2 | -32,768 ~ 32,767 | 0 | |
| int | 4 | -2³¹ ~ 2³¹-1 (约±21亿) | 0 | |
| long | 8 | -2⁶³ ~ 2⁶³-1 | 0L | |
| 浮点型 | float | 4 | IEEE 754单精度 (6-7位) | 0.0f |
| double | 8 | IEEE 754双精度 (15位) | 0.0d | |
| 字符型 | char | 2 | 0 ~ 65,535 (Unicode) | '\u0000' |
| 布尔型 | boolean | 未规定 | true/false | false |
1.2 特殊说明
boolean的大小问题
boolean理论上1个bit就够,但JVM实际处理:
1. 单独变量:通常占1字节
2. 编译时转换:用int表示(1=true, 0=false)
3. boolean数组:通过byte数组实现
为什么不规定大小?
- JVM规范未强制,给不同实现留空间
- 单变量用1字节对齐效率高
- 数组场景按 byte 数组实现(1 元素 1 字节);bit 级压缩交给
java.util.BitSet这类工具类
char与C++的区别
Java: 2字节,存储Unicode字符
char c = '中'; // 支持中文
C++: 1字节(语言规定 sizeof(char) 恒等于 1)
char c = 'A'; // 1字节可承载 ASCII/UTF-8 字节
wchar_t wc = L'中'; // 宽字符,宽度随平台(Windows 2字节、Linux 4字节)
char 的 Unicode 陷阱
// char 范围:0-65535(16位)
char c1 = '中'; // ✅ BMP 字符(U+0000 ~ U+FFFF)
char c2 = 0x1F600; // ❌ 编译错误(Emoji 超出范围)
// Unicode 补充字符(需要 2 个 char)
String emoji = "😀";
System.out.println(emoji.length()); // 2(不是 1!)
System.out.println(emoji.codePointCount(0, emoji.length())); // 1 ✅
// 1. 一个 char 能存储所有 Unicode 字符吗?❌
// 2. String.length() 返回的是什么?(char 数量,非字符数)
// 3. 如何正确遍历字符串?(使用 codePoints())
二、包装类(Wrapper Class)
2.1 为什么需要包装类?
核心原因:基本类型不是对象,无法参与面向对象编程
// ❌ 编译错误:集合只能存对象
List<int> list = new ArrayList<>();
// ✅ 正确:使用包装类
List<Integer> list = new ArrayList<>();
2.2 基本类型与包装类对应关系
| 基本类型 | 包装类 | 父类 |
|---|---|---|
| byte | Byte | Number |
| short | Short | Number |
| int | Integer | Number |
| long | Long | Number |
| float | Float | Number |
| double | Double | Number |
| char | Character | Object |
| boolean | Boolean | Object |
继承体系:
Object
├── Number (抽象类)
│ ├── Byte
│ ├── Short
│ ├── Integer
│ ├── Long
│ ├── Float
│ └── Double
├── Character
└── Boolean
2.3 包装类的核心特性
① 不可变性(Immutable)
Integer a = 10;
a = 20; // 不是修改原对象,而是创建新对象
② 提供工具方法
// 类型转换
int i = Integer.parseInt("123");
String s = Integer.toString(456);
// 进制转换
String binary = Integer.toBinaryString(10); // "1010"
String hex = Integer.toHexString(255); // "ff"
// 比较方法
int result = Integer.compare(10, 20); // -1
③ 常量定义
Integer.MAX_VALUE // 2147483647
Integer.MIN_VALUE // -2147483648
Integer.SIZE // 32 (位数)
Integer.BYTES // 4 (字节数)
三、基本类型 vs 包装类
3.1 核心区别
| 对比维度 | 基本类型 | 包装类 |
|---|---|---|
| 存储位置 | 栈内存 | 堆内存(对象) |
| 默认值 | 有(如int为0) | null |
| 性能 | 高(直接操作值) | 低(对象开销) |
| 空值支持 | 不支持 | 支持null |
| 集合支持 | 不支持 | 支持 |
| 方法调用 | 不支持 | 支持 |
3.2 使用场景选择
// ✅ 优先使用基本类型(性能优先)
public void calculate(int count) {
for (int i = 0; i < count; i++) {
// 高频运算
}
}
// ✅ 必须用包装类的场景
List<Integer> list = new ArrayList<>(); // 集合
Map<String, Long> map = new HashMap<>(); // 泛型
// ✅ 可能为null的场景用包装类
public Integer getUserAge(String userId) {
User user = findUser(userId);
return user != null ? user.getAge() : null; // null表示未找到
}
// ❌ 避免混用导致性能问题
List<Integer> list = new ArrayList<>();
for (int i = 0; i < 10000; i++) {
list.add(i); // 频繁装箱,创建10000个Integer对象
}
四、与C/C++的关键区别
4.1 固定大小 vs 平台相关
// Java: int永远是4字节(跨平台一致)
int i = 10;
// C++: int可能是2或4字节(取决于平台)
// int i = 10; // 在32位系统可能是4字节,16位系统可能是2字节
4.2 空值支持
// Java: 基本类型不能为null
int x = null; // ❌ 编译错误
Integer y = null; // ✅ 包装类可以
// C++: 可通过指针实现
// int* p = nullptr; // ✅ 指针可为空
4.3 默认值
// Java: 成员变量有默认值
class Demo {
int count; // 自动初始化为0
boolean flag; // 自动初始化为false
}
// Java: 局部变量必须显式初始化
void method() {
int x;
System.out.println(x); // ❌ 编译错误:未初始化
}
// C++: 都不会自动初始化(未定义行为)
五、高频面试题
Q1: Java有哪些基本数据类型?各占多少字节?
答: 8种:
- 整型:byte(1)、short(2)、int(4)、long(8)
- 浮点:float(4)、double(8)
- 字符:char(2)
- 布尔:boolean(未规定,通常1字节)
Q2: 为什么Java要设计基本类型和包装类型?
答:
- 性能考虑:基本类型直接存储值,运算效率高
- 对象化需求:集合、泛型必须用对象
- 功能扩展:包装类提供工具方法(如parseInt)
- 兼容设计:保留C/C++的高性能特性,又支持面向对象
Q3: int和Integer有什么区别?分别适用于哪些场景?
答:
- int:基本类型,性能高,不能为null,适合高频计算
- Integer:对象类型,功能丰富,可为null,适合集合、泛型
场景选择:
// 优先int:循环、运算、局部变量
for (int i = 0; i < 10000; i++) { }
// 必须Integer:集合、泛型、可能为null
List<Integer> list = new ArrayList<>();
Q4: List<int> 为什么不合法?怎么解决?
答:
- 原因:泛型要求类型参数必须是对象,int不是对象
- 解决:使用包装类
List<Integer> - 性能优化:元素量大、性能敏感的场景改用基本类型数组
int[](从 Java 1.0 起就可用,与任何 JDK 版本无关),或引入 fastutil / Eclipse Collections 这类提供IntList的基本类型集合库,省掉每个元素的包装对象开销
Q5: 为什么char在Java中占2字节,而C++中占1字节?
答:
- Java:char 是 UTF-16 的编码单元,固定 2 字节——一个 char 装一个 UTF-16 码元,天然覆盖中文等 BMP 字符;Emoji 等增补字符需要两个 char(代理对)
- C++:1 字节是语言规定(sizeof(char) 恒等于 1,字节的位数由实现决定、通常为 8),ASCII 和 UTF-8 字节都用它承载,与"只支持英文"无关
- 扩展:C++ 需要更宽的字符类型时用
wchar_t(宽度随平台:Windows 2 字节、Linux 4 字节);要定宽可移植就用 C++11 的char16_t/char32_t
相关链接
- 02-自动装拆箱 - 基本类型与包装类如何自动转换?
- 03-缓存池机制 - 为什么
Integer a=127; b=127; a==b为true? - 04-类型转换规则 - 隐式转换、强制转换、精度丢失
记忆口诀
8种基本类型:
四整两浮一字符,布尔独立记心间 byte short int long,float double细分辨 char支持万国码,boolean真假判
包装类命名:
六个Number是数字,Character字符独,Boolean布尔殊 Integer特别记,其余首字母大写即可
💬 评论