Appearance
数据类型与类型转换
这篇笔记聚焦 Java 里最基础、但也最容易“会用却没讲透”的一条主线:
- 数据类型到底怎么分类
- 基本数据类型和引用数据类型有什么区别
- 包装类型为什么会出现
- 自动装箱、拆箱和类型转换在解决什么问题
==、equals、String这些高频易混点到底该怎么理解
如果这条线没有打稳,后面学集合、泛型、并发和 JVM 时,很容易不断碰到边界理解不清的问题。
1. Java 的数据类型怎么分类
Java 的数据类型可以分成两大类:
基本数据类型引用数据类型
这是最基础、也最重要的一层划分。
1.1 基本数据类型
基本数据类型 可以理解成 Java 语言内置的、用于直接表示简单数值或逻辑值的类型。
它们不是对象,重点是:值本身就是数据。
Java 一共有 8 种基本数据类型:
byteshortintlongfloatdoublecharboolean
1.2 引用数据类型
引用数据类型 可以理解成 变量里保存的不是对象本体,而是指向对象的引用。
常见的引用数据类型包括:
- 类
- 接口
- 数组
- 枚举
- 字符串
例如:
java
String name = "Java";
int[] nums = {1, 2, 3};这里的 String 和数组都属于引用数据类型。
2. 8 种基本数据类型分别是什么
| 类型 | 含义 | 常见用途 |
|---|---|---|
byte | 8 位整数 | 节省空间、字节流处理 |
short | 16 位整数 | 较少单独使用 |
int | 32 位整数 | 最常见的整数类型 |
long | 64 位整数 | 大范围整数、时间戳等 |
float | 单精度浮点数 | 较少作为精确计算首选 |
double | 双精度浮点数 | 更常见的小数类型 |
char | 字符类型 | 表示单个字符 |
boolean | 布尔类型 | 表示真/假 |
这里要注意:
char 虽然看起来像字符,但底层本质上仍然是一个数值型编码单元。
3. 为什么 int 最常见,而不是 byte 或 short
很多人初学时会觉得:
byte 更省空间,是不是应该优先用它?
工程上通常不是这样。
更常见的原因是:
int是整数计算里最自然、最常用的默认类型- CPU 和 JVM 对
int的处理通常更直接 byte和short在表达式里经常还会被提升成int
所以日常业务代码里,如果只是普通整数,默认优先考虑的通常是:int
4. 基本类型和引用类型最核心的区别是什么
可以抓住这几个点:
| 对比项 | 基本数据类型 | 引用数据类型 |
|---|---|---|
| 保存的是什么 | 值本身 | 对象引用 |
| 是否是对象 | 否 | 是 |
是否可为 null | 否 | 可以 |
| 默认值形态 | 数值/布尔值 | null |
更直白一点说:
int a = 10;,a里就是10String s = "abc";,s里更像是“指向这个字符串对象的位置”
5. 包装类型是什么,为什么会出现
Java 为每种基本数据类型都提供了对应的 包装类型。
它可以理解成 把原本不是对象的基本类型,包装成一个对象类型。
对应关系如下:
| 基本类型 | 包装类型 |
|---|---|
byte | Byte |
short | Short |
int | Integer |
long | Long |
float | Float |
double | Double |
char | Character |
boolean | Boolean |
包装类型出现的原因,核心是:Java 很多地方只能处理对象,不能直接处理基本类型。
比如:
- 泛型不能直接写
List<int> - 集合里放的是对象
- 某些 API 需要对象语义
所以你会看到:
java
List<Integer> ids = new ArrayList<>();而不会是:
java
List<int> ids = new ArrayList<>();6. 自动装箱和拆箱是什么
6.1 自动装箱
自动装箱 可以理解成 把基本类型自动转换成对应的包装类型对象。
例如:
java
Integer x = 10;这背后本质上相当于:
java
Integer x = Integer.valueOf(10);6.2 自动拆箱
自动拆箱 可以理解成 把包装类型对象自动转换回基本类型值。
例如:
java
Integer x = 10;
int y = x;这背后本质上相当于:
java
int y = x.intValue();7. 自动装箱拆箱为什么容易出问题
因为它看起来像“自然语法”,但背后其实有对象和空值边界。
例如:
java
Integer x = null;
int y = x;这段代码会抛出:NullPointerException
原因不是 int 有问题,而是:拆箱时需要从 Integer 对象里取出 int 值,但对象本身是 null。
所以包装类型参与运算时,一定要注意:
- 是否可能为
null - 是否发生自动拆箱
8. 类型转换到底在说什么
类型转换 可以理解成 把一个类型的值,按规则转换成另一个类型来使用。
在 Java 里,最常见分成两类:
- 自动类型提升
- 强制类型转换
8.1 自动类型提升
例如:
java
int a = 10;
long b = a;这里是自动完成的,因为从较小范围整数到更大范围整数,通常不会丢失信息。
8.2 强制类型转换
例如:
java
double x = 10.8;
int y = (int) x;这里必须显式写:
java
(int)因为从 double 到 int 可能会丢失信息。
这个过程不是“四舍五入”,而是:直接截断小数部分
所以结果会是:10
9. 表达式里的类型提升为什么容易让人困惑
因为有些看起来是小类型的运算,实际结果会先提升。
例如:
java
byte a = 1;
byte b = 2;
byte c = (byte) (a + b);这里 a + b 的结果在表达式计算时会先提升为 int。
所以如果直接写:
java
byte c = a + b;编译会报错。
这就是为什么很多人会觉得:
“明明两个 byte 相加,结果为什么不能直接放 byte?”
直接说:Java 的数值表达式有自己的类型提升规则。
10. == 和 equals 有什么区别
这是 Java 数据类型里最常见的混淆点之一。
10.1 对基本类型使用 ==
比较的是:值是否相等
例如:
java
int a = 10;
int b = 10;
System.out.println(a == b); // true10.2 对引用类型使用 ==
比较的是:两个引用是否指向同一个对象
它不一定表示“内容相等”。
10.3 equals
equals 可以理解成 对象内容是否相等的一种逻辑比较方式。
但前提是:这个类正确重写了 equals 方法。
如果想继续系统看:
equals和==到底差在哪里- 为什么重写
equals时通常还要重写hashCode - 它们在
HashMap、HashSet中是怎么协同工作的
可以继续看:
例如:
java
String a = new String("abc");
String b = new String("abc");
System.out.println(a == b); // false
System.out.println(a.equals(b)); // true11. String 为什么总是被单独拿出来讲
因为 String 虽然是引用类型,但它在 Java 里非常特殊。
String 可以理解成 表示字符串内容的不可变对象。
这里的 不可变,指的是:一旦创建,字符串对象本身的内容就不能再被修改。
它解决的是:
- 字符串共享更安全
- 哈希更稳定
- 在并发和常量池场景下更容易管理
12. 字符串常量池是什么
字符串常量池 可以理解成 JVM 为了复用字符串常量,专门维护的一块共享区域。
例如:
java
String a = "hello";
String b = "hello";
System.out.println(a == b); // true这里 a 和 b 指向的通常是同一个常量池中的字符串对象。
但如果写成:
java
String a = new String("hello");
String b = new String("hello");
System.out.println(a == b); // false那就是两个新对象。
所以 String 相关问题之所以容易混,是因为它同时涉及:
- 引用类型比较
- 对象内容比较
- 常量池复用
13. 小数为什么不建议直接用 float / double 做精确计算
因为 float 和 double 是浮点数类型,很多十进制小数在二进制里不能被精确表示。
这会导致:
- 精度误差
- 金额计算不准确
例如:
java
System.out.println(0.1 + 0.2);结果通常不会是你直觉里的精确 0.3。
所以在金额、计费这类精度敏感场景,更常见的做法是:使用 BigDecimal
BigDecimal 可以理解成 用于高精度数值计算的一种类,特别适合金额和精确小数场景。
14. 常见误区
14.1 误区一:包装类型和基本类型没区别
不对。
它们在:
- 是否是对象
- 是否可为
null - 是否参与装箱拆箱
- 是否能用于泛型
这些方面都有明显区别。
14.2 误区二:== 就是比较“内容一样不一样”
不准确。
对引用类型来说,== 更常是在比较:是不是同一个对象
14.3 误区三:double 足够表示所有小数
不对。
它适合一般浮点运算,但不适合要求严格精度的金额类场景。
15. 一句话总结
Java 的数据类型与类型转换这条主线,本质上是在解决:
值和对象到底如何表示、类型之间如何安全转换、哪些语言细节会在实际开发里引发空值、精度和比较语义问题。