主题
Chapter 02 · 变量与数据类型
编程的本质,是教计算机存数据、算数据、改数据。变量就是存数据的"盒子"。
🎯 本章目标
- 理解什么是 变量,会声明、赋值、使用
- 记住 Java 的 8 种基本数据类型 及其取值范围
- 区分 基本类型 vs 引用类型
- 掌握 类型转换(自动 / 强制)的规则
- 学会用 常量 和给变量取个好名字
1. 变量是什么?盒子的故事
想象你家有一排标着名字的抽屉:
- 抽屉上贴着标签 "age",里面放着数字 18
- 抽屉 "name" 里放着字符串 "张三"
- 抽屉 "isStudent" 里放着
true
这些抽屉就是 变量:
- 标签 = 变量名
- 抽屉的尺寸 = 数据类型(大抽屉放大数据,小抽屉放小数据,类型决定了能放什么)
- 里面的东西 = 变量值
java
int age = 18; // 标签 age 的整数抽屉,放 18
String name = "张三"; // 标签 name 的字符串抽屉,放 "张三"
boolean isStudent = true; // 标签 isStudent 的布尔抽屉,放 true💡 重点:Java 是 强类型语言,抽屉一旦标了类型,就不能塞别的类型进去(不像 Python 那么随便)。
2. 变量的三件事:声明、赋值、使用
java
int score; // ① 声明:开一个 int 类型的抽屉,标签叫 score
score = 95; // ② 赋值:把 95 放进去
System.out.println(score); // ③ 使用:取出来看看
int level = 1; // 声明 + 赋值合并成一行(最常用)口诀:先有抽屉,才能放东西;放东西前不能用。
java
int x;
System.out.println(x); // ❌ 报错:可能尚未初始化变量 x3. 八大基本数据类型(必背)
Java 有 8 种基本数据类型(也叫"原始类型"),分 4 大类:
3.1 整数类型(4 种)
| 类型 | 占用空间 | 取值范围 | 默认值 | 生活举例 |
|---|---|---|---|---|
byte | 1 字节 | -128 ~ 127 | 0 | 一个像素的灰度值 |
short | 2 字节 | -32768 ~ 32767 | 0 | 一个游戏角色的血量 |
int | 4 字节 | 约 ±21 亿 | 0 | 最常用的整数(年龄、订单 id 等) |
long | 8 字节 | 约 ±922 亿亿 | 0L | 时间戳、大订单 id |
java
byte b = 100;
short s = 30000;
int age = 25;
long worldPopulation = 8_100_000_000L; // long 字面量加 L 后缀🤓 小知识:JDK 7 起,数字字面量可以用下划线
_分隔提高可读性,比如1_000_000等于1000000。
3.2 浮点类型(2 种)
| 类型 | 占用空间 | 精度 | 默认值 | 生活举例 |
|---|---|---|---|---|
float | 4 字节 | 约 7 位有效数字 | 0.0f | 单精度浮点(少用) |
double | 8 字节 | 约 15 位有效数字 | 0.0 | 小数默认选择 |
java
double price = 99.99;
float pi = 3.14f; // float 字面量必须加 f 后缀(否则被当作 double)⚠️ 浮点数有精度问题:
0.1 + 0.2不等于0.3,等于0.30000000000000004。金额计算必须用BigDecimal!
3.3 字符类型(1 种)
| 类型 | 占用空间 | 取值范围 | 默认值 |
|---|---|---|---|
char | 2 字节 | 0 ~ 65535(Unicode) | \u0000 |
java
char c1 = 'A'; // 单引号包字符
char c2 = '中'; // 支持中文
char c3 = 65; // 等价于 'A',因为 'A' 的 Unicode 是 65
char c4 = '\n'; // 转义字符:换行💡 char vs String:
'A'(单引号)是 char,"A"(双引号)是 String。两者完全不同!
3.4 布尔类型(1 种)
| 类型 | 取值 | 默认值 |
|---|---|---|
boolean | true 或 false | false |
java
boolean isAdult = age >= 18;
boolean hasPermission = false;🚫 Java 与 C/Python 的区别:Java 的 boolean 不能用 0/1 代替,也不能写
if (x)这种把 int 当 boolean 用的代码。
4. 基本类型 vs 引用类型
Java 数据类型的"双轨制":
| 对比 | 基本类型 | 引用类型 |
|---|---|---|
| 关键字 | int double boolean 等 8 种 | String 数组 自定义类 等 |
| 存储位置 | 栈(直接存值) | 栈存"地址",堆存对象 |
| 默认值 | 0 / 0.0 / false / \u0000 | null |
| 比较 | == 比较 值 | == 比较 地址,要比内容用 equals() |
java
int a = 10;
int b = 10;
System.out.println(a == b); // true,比较值
String s1 = new String("hello");
String s2 = new String("hello");
System.out.println(s1 == s2); // false!比较的是地址
System.out.println(s1.equals(s2)); // true,比较内容🚨 新手最大坑:用
==比较两个 String,看似一样却返回 false。字符串比较一律用.equals()!
5. 类型转换:抽屉之间倒东西
5.1 自动类型转换(隐式)
小抽屉的东西可以直接倒进大抽屉。
java
int i = 100;
long l = i; // ✅ int → long,自动
double d = l; // ✅ long → double,自动转换路径(从小到大,编译器自动加):
byte → short → int → long → float → double
↑
char5.2 强制类型转换(显式)
大抽屉的东西要倒进小抽屉,必须手动 cast,并承担数据丢失的风险。
java
double d = 3.99;
int i = (int) d; // 3(小数部分丢失,不是四舍五入!)
long big = 10_000_000_000L;
int small = (int) big; // 数据溢出,结果不可预测5.3 表达式中的自动提升
java
byte a = 10;
byte b = 20;
byte c = a + b; // ❌ 编译错误!
// 因为 byte 在表达式中会被自动提升为 int
byte c = (byte)(a + b); // ✅ 强转回来规则:byte/short/char 参与运算时,会先全部提升为 int 再计算。
6. 常量:永不改变的"封印"
用 final 修饰的变量就是常量,赋值后不能再改:
java
final double PI = 3.14159;
final int MAX_AGE = 150;
PI = 3.14; // ❌ 编译错误:cannot assign a value to final variable惯例:常量名 全大写 + 下划线分隔,如 MAX_RETRY_COUNT。
💡 为什么要用常量?防止"魔法数字"散落各处,改起来烦还容易出错。
7. 变量命名:别让人看不懂
硬性规则
- 由 字母、数字、
_、$组成 - 不能以数字开头
- 不能用关键字(如
int、class、public) - 区分大小写(
age和Age是两个变量)
行业惯例(强烈遵守)
| 类型 | 命名规则 | 例子 |
|---|---|---|
| 普通变量 | 小驼峰 | userName、orderCount |
| 常量 | 大写 + 下划线 | MAX_SIZE、DEFAULT_TIMEOUT |
| 类名 | 大驼峰 | UserService、OrderController |
| 包名 | 全小写 | com.example.demo |
java
// ❌ 不推荐
int a; // 不知道在干嘛
int x1, x2; // 同上
String 名字; // 中文虽然能用,但极不专业
// ✅ 推荐
int userAge;
String userName;
final int MAX_LOGIN_ATTEMPTS = 5;8. 实战练习
进入 code/ 目录,依次运行:
| 文件 | 内容 |
|---|---|
VariableDemo.java | 8 种基本类型的声明与打印 |
TypeConversionDemo.java | 自动转换 vs 强制转换实操 |
PrecisionPitfall.java | 浮点数精度问题与 BigDecimal 解决方案 |
bash
javac VariableDemo.java
java VariableDemo9. 浏览器演示
打开 demo.html 体验:
- 八大类型取值范围动态查看
- 类型转换交互演示
- 浮点精度问题现场翻车
10. 面试可能会问什么?
Q1: Java 有哪些基本数据类型?
参考答案:8 种,分 4 类:
- 整数(4):byte(1B)、short(2B)、int(4B)、long(8B)
- 浮点(2):float(4B)、double(8B)
- 字符(1):char(2B)
- 布尔(1):boolean
Q2: int 和 Integer 有什么区别?
| 对比 | int | Integer |
|---|---|---|
| 类型 | 基本类型 | 包装类(引用类型) |
| 默认值 | 0 | null |
| 存储 | 栈 | 堆(引用在栈) |
| 能否为 null | 否 | 是 |
| 集合中能用吗 | 否(List<int> 不行) | 是(List<Integer>) |
Q3: 0.1 + 0.2 == 0.3 的结果是?
答:false。因为浮点数在二进制中无法精确表示(就像 1/3 在十进制中无法精确表示),实际结果是 0.30000000000000004。
解决方案:用 BigDecimal:
java
BigDecimal a = new BigDecimal("0.1");
BigDecimal b = new BigDecimal("0.2");
System.out.println(a.add(b)); // 0.3Q4: char 能存中文吗?
答:可以。Java 的 char 是 2 字节(16 位),采用 Unicode 编码,可以表示绝大多数常见字符(包括中文)。但对于某些 emoji 等"补充字符"(4 字节 UTF-16),需要用 String 或 int(codepoint)处理。
Q5: byte b = 130; 编译会报错吗?
答:会。byte 范围是 -128 ~ 127,130 超出范围,编译器报错。 要存可以强转:byte b = (byte) 130;,结果是 -126(溢出)。
Q6: 类型转换的隐藏陷阱
java
short s1 = 1;
s1 = s1 + 1; // ❌ 编译错误:表达式 s1+1 是 int
s1 += 1; // ✅ 编译通过:+= 内置了强转
int i = 1000_000_000;
int j = i + i; // 溢出!结果是 -294967296,不报错Q7: 为什么不推荐用 float 算钱?
答:float 只有 7 位精度,而且二进制无法精确表示十进制小数。比如:
java
float price = 1.1f;
float total = price * 3; // 3.3000002,不是 3.3金额必须用 BigDecimal,并用字符串构造:new BigDecimal("1.1"),不要用 double 构造。
🎁 本章小结
✅ 8 种基本类型必背:byte/short/int/long、float/double、char、boolean
✅ 整数默认 int,小数默认 double
✅ 引用类型 == 比地址,equals 比内容
✅ 自动转换:小→大;强制转换:大→小(注意溢出/精度丢失)
✅ 金额一律用 BigDecimal🔗 导航
- ⬅️ 上一章:Chapter 01 · 走进 Java 世界
- ➡️ 下一章:Chapter 03 · 运算符与表达式