--- title: "01-基本类型与包装类" created: 2025-11-25 tags: - Java --- # 基本类型与包装类 ## 核心概念 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 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 陷阱 ```java // 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 为什么需要包装类? **核心原因:基本类型不是对象,无法参与面向对象编程** ```java // ❌ 编译错误:集合只能存对象 List list = new ArrayList<>(); // ✅ 正确:使用包装类 List 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) ```java Integer a = 10; a = 20; // 不是修改原对象,而是创建新对象 ``` #### ② 提供工具方法 ```java // 类型转换 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 ``` #### ③ 常量定义 ```java Integer.MAX_VALUE // 2147483647 Integer.MIN_VALUE // -2147483648 Integer.SIZE // 32 (位数) Integer.BYTES // 4 (字节数) ``` --- ## 三、基本类型 vs 包装类 ### 3.1 核心区别 | 对比维度 | 基本类型 | 包装类 | | --- | --- | --- | | 存储位置 | 栈内存 | 堆内存(对象) | | 默认值 | 有(如int为0) | null | | 性能 | 高(直接操作值) | 低(对象开销) | | 空值支持 | 不支持 | 支持null | | 集合支持 | 不支持 | 支持 | | 方法调用 | 不支持 | 支持 | ### 3.2 使用场景选择 ```java // ✅ 优先使用基本类型(性能优先) public void calculate(int count) { for (int i = 0; i < count; i++) { // 高频运算 } } // ✅ 必须用包装类的场景 List list = new ArrayList<>(); // 集合 Map map = new HashMap<>(); // 泛型 // ✅ 可能为null的场景用包装类 public Integer getUserAge(String userId) { User user = findUser(userId); return user != null ? user.getAge() : null; // null表示未找到 } // ❌ 避免混用导致性能问题 List list = new ArrayList<>(); for (int i = 0; i < 10000; i++) { list.add(i); // 频繁装箱,创建10000个Integer对象 } ``` --- ## 四、与C/C++的关键区别 ### 4.1 固定大小 vs 平台相关 ```java // Java: int永远是4字节(跨平台一致) int i = 10; // C++: int可能是2或4字节(取决于平台) // int i = 10; // 在32位系统可能是4字节,16位系统可能是2字节 ``` ### 4.2 空值支持 ```java // Java: 基本类型不能为null int x = null; // ❌ 编译错误 Integer y = null; // ✅ 包装类可以 // C++: 可通过指针实现 // int* p = nullptr; // ✅ 指针可为空 ``` ### 4.3 默认值 ```java // 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要设计基本类型和包装类型? **答:** 1. **性能考虑**:基本类型直接存储值,运算效率高 2. **对象化需求**:集合、泛型必须用对象 3. **功能扩展**:包装类提供工具方法(如parseInt) 4. **兼容设计**:保留C/C++的高性能特性,又支持面向对象 ### Q3: int和Integer有什么区别?分别适用于哪些场景? **答:** - **int**:基本类型,性能高,不能为null,适合高频计算 - **Integer**:对象类型,功能丰富,可为null,适合集合、泛型 **场景选择:** ```java // 优先int:循环、运算、局部变量 for (int i = 0; i < 10000; i++) { } // 必须Integer:集合、泛型、可能为null List list = new ArrayList<>(); ``` ### Q4: `List` 为什么不合法?怎么解决? **答:** - **原因**:泛型要求类型参数必须是对象,int不是对象 - **解决**:使用包装类 `List` - **性能优化**:元素量大、性能敏感的场景改用基本类型数组 `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-自动装拆箱|02-自动装拆箱]] - 基本类型与包装类如何自动转换? - [[03-缓存池机制(Cache Pool)|03-缓存池机制]] - 为什么`Integer a=127; b=127; a==b`为true? - [[04-类型转换规则|04-类型转换规则]] - 隐式转换、强制转换、精度丢失 --- ## 记忆口诀 **8种基本类型:** > 四整两浮一字符,布尔独立记心间 > byte short int long,float double细分辨 > char支持万国码,boolean真假判 **包装类命名:** > 六个Number是数字,Character字符独,Boolean布尔殊 > Integer特别记,其余首字母大写即可 --- ⬅️ [[00-基础概览|基础概览]] 🏠 [[00-Java|00-Java]] ➡️ [[02-自动装拆箱|自动装拆箱]]