Skip to content

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);  // ❌ 报错:可能尚未初始化变量 x

3. 八大基本数据类型(必背)

Java 有 8 种基本数据类型(也叫"原始类型"),分 4 大类:

Java 基本数据类型

3.1 整数类型(4 种)

类型占用空间取值范围默认值生活举例
byte1 字节-128 ~ 1270一个像素的灰度值
short2 字节-32768 ~ 327670一个游戏角色的血量
int4 字节约 ±21 亿0最常用的整数(年龄、订单 id 等)
long8 字节约 ±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 种)

类型占用空间精度默认值生活举例
float4 字节约 7 位有效数字0.0f单精度浮点(少用)
double8 字节约 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 种)

类型占用空间取值范围默认值
char2 字节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 种)

类型取值默认值
booleantruefalsefalse
java
boolean isAdult = age >= 18;
boolean hasPermission = false;

🚫 Java 与 C/Python 的区别:Java 的 boolean 不能用 0/1 代替,也不能写 if (x) 这种把 int 当 boolean 用的代码。


4. 基本类型 vs 引用类型

Java 数据类型的"双轨制":

基本类型 vs 引用类型

对比基本类型引用类型
关键字int double boolean 等 8 种String 数组 自定义类
存储位置(直接存值)栈存"地址",存对象
默认值0 / 0.0 / false / \u0000null
比较== 比较 == 比较 地址,要比内容用 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

            char

5.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. 变量命名:别让人看不懂

硬性规则

  • 字母、数字、_$ 组成
  • 不能以数字开头
  • 不能用关键字(如 intclasspublic
  • 区分大小写(ageAge 是两个变量)

行业惯例(强烈遵守)

类型命名规则例子
普通变量小驼峰userNameorderCount
常量大写 + 下划线MAX_SIZEDEFAULT_TIMEOUT
类名大驼峰UserServiceOrderController
包名全小写com.example.demo
java
// ❌ 不推荐
int a;       // 不知道在干嘛
int x1, x2;  // 同上
String 名字; // 中文虽然能用,但极不专业

// ✅ 推荐
int userAge;
String userName;
final int MAX_LOGIN_ATTEMPTS = 5;

8. 实战练习

进入 code/ 目录,依次运行:

文件内容
VariableDemo.java8 种基本类型的声明与打印
TypeConversionDemo.java自动转换 vs 强制转换实操
PrecisionPitfall.java浮点数精度问题与 BigDecimal 解决方案
bash
javac VariableDemo.java
java VariableDemo

9. 浏览器演示

打开 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: intInteger 有什么区别?

对比intInteger
类型基本类型包装类(引用类型)
默认值0null
存储堆(引用在栈)
能否为 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.3

Q4: 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

🔗 导航