Appearance
第1课:变量与数据类型
🎯 学习目标
- 掌握 Java 的 8 种基本数据类型
- 理解基本类型与引用类型的区别
- 掌握类型转换规则
- 理解变量的作用域和生命周期
📖 一、Java 类型体系概览
Java 有两大类型系统:
Java 数据类型
├── 基本类型(Primitive Types)- 8种
│ ├── 整数型:byte, short, int, long
│ ├── 浮点型:float, double
│ ├── 字符型:char
│ └── 布尔型:boolean
└── 引用类型(Reference Types)
├── 类(Class)
├── 接口(Interface)
├── 数组(Array)
└── 枚举(Enum)📖 二、8种基本数据类型详解
1. 整数类型
| 类型 | 字节数 | 取值范围 | 默认值 |
|---|---|---|---|
| byte | 1字节 | -128 ~ 127 | 0 |
| short | 2字节 | -32,768 ~ 32,767 | 0 |
| int | 4字节 | -2^31 ~ 2^31-1 | 0 |
| long | 8字节 | -2^63 ~ 2^63-1 | 0L |
java
byte age = 25;
short year = 2024;
int population = 1_400_000_000; // 下划线分隔,增强可读性
long distance = 9_460_000_000_000L; // 后缀 L 或 l2. 浮点类型
| 类型 | 字节数 | 精度 | 默认值 |
|---|---|---|---|
| float | 4字节 | 7位有效数字 | 0.0f |
| double | 8字节 | 15位有效数字 | 0.0d |
java
float price = 19.99f; // 必须加 f 后缀
double pi = 3.141592653589793; // 通常用 double⚠️ 浮点数陷阱:
java
double d = 0.1 + 0.2;
System.out.println(d); // 输出 0.30000000000000004,不是 0.3!
// 原因:二进制无法精确表示某些十进制小数3. 字符类型
java
char letter = 'A'; // 单引号,只能一个字符
char chinese = '中'; // 支持 Unicode
char unicode = '中'; // Unicode 表示法
char newline = '\n'; // 转义字符常用转义字符:
\n- 换行\t- 制表符\\- 反斜杠\'- 单引号\"- 双引号
4. 布尔类型
java
boolean isStudent = true;
boolean isPassed = false;⚠️ Java vs C 的区别:
java
// ❌ Java 不允许(C 语言可以)
int x = 1;
if (x) { // 编译错误!必须是 boolean
// ...
}
// ✅ Java 正确写法
if (x != 0) { // 显式比较
// ...
}📖 三、引用类型
String(字符串)
java
String name = "Alice"; // 最常用的引用类型
String empty = ""; // 空字符串
String nullStr = null; // null 表示不指向任何对象🔑 关键区别:基本类型 vs 引用类型
java
// 基本类型:直接存储值
int a = 10;
int b = a;
b = 20;
System.out.println(a); // 输出 10,a 不受影响
// 引用类型:存储对象的地址
StringBuilder sb1 = new StringBuilder("Hello");
StringBuilder sb2 = sb1; // sb2 指向同一个对象
sb2.append(" World");
System.out.println(sb1); // 输出 "Hello World",sb1 也改变了!📖 四、类型转换
1. 自动类型转换(隐式转换)
规则:小范围 → 大范围,自动转换
byte → short → int → long → float → double
char ↗java
int i = 100;
long l = i; // int → long,自动
double d = i; // int → double,自动
float f = l; // long → float,自动
byte b = 10;
int x = b + 5; // byte 自动提升为 int2. 强制类型转换(显式转换)
规则:大范围 → 小范围,需要强制转换
java
double d = 3.14;
int i = (int) d; // 3,小数部分被截断
long l = 100L;
int x = (int) l; // 100
int big = 130;
byte small = (byte) big; // -126,超出范围会溢出!⚠️ 强制转换的风险:
java
int i = 128;
byte b = (byte) i; // 结果是 -128,发生溢出!3. 表达式中的自动提升
java
byte b1 = 10;
byte b2 = 20;
byte b3 = b1 + b2; // ❌ 编译错误!
// 原因:byte + byte 会自动提升为 int
int result = b1 + b2; // ✅ 正确
// 或者强制转换
byte b3 = (byte)(b1 + b2); // ✅ 正确📖 五、变量声明与初始化
1. 变量声明
java
int age; // 声明,未初始化
age = 25; // 赋值
int score = 90; // 声明并初始化
int a, b, c; // 同时声明多个变量
int x = 1, y = 2; // 声明并初始化多个变量2. 常量(final)
java
final double PI = 3.14159; // 常量命名:全大写+下划线
PI = 3.14; // ❌ 编译错误!常量不能修改
final int MAX_SIZE = 100;3. 变量命名规范
java
// ✅ 推荐
int studentAge; // 驼峰命名
String userName;
final int MAX_COUNT = 100; // 常量:大写+下划线
// ❌ 不推荐
int student_age; // C 风格
int a, b, c; // 名字太短,无意义
int 123abc; // ❌ 不能以数字开头
int class; // ❌ 不能用关键字📖 六、常见陷阱与注意事项
陷阱1:整数除法
java
int a = 5, b = 2;
System.out.println(a / b); // 输出 2,不是 2.5!
System.out.println(a / (double)b); // 输出 2.5陷阱2:long 字面量
java
long big = 3000000000; // ❌ 编译错误!字面量默认是 int
long big = 3000000000L; // ✅ 加 L 后缀陷阱3:char 运算
java
char c = 'A';
System.out.println(c + 1); // 输出 66(ASCII 码)
System.out.println((char)(c + 1)); // 输出 'B'陷阱4:浮点数比较
java
double d1 = 0.1 + 0.2;
double d2 = 0.3;
System.out.println(d1 == d2); // false!
// 正确的比较方式
double epsilon = 0.0000001;
System.out.println(Math.abs(d1 - d2) < epsilon); // true🆚 Java vs C 对比
| 特性 | C 语言 | Java |
|---|---|---|
| 布尔类型 | 无(用 int) | boolean (true/false) |
| 字符串 | char* 或 char[] | String 对象 |
| 类型大小 | 平台相关(int 可能2或4字节) | 固定大小(int 始终4字节) |
| 数组越界 | 不检查(导致崩溃) | 运行时检查(抛异常) |
| 类型转换 | 隐式转换较多 | 更严格,需显式转换 |
| 未初始化变量 | 随机值 | 成员变量有默认值,局部变量必须初始化 |
💡 最佳实践
优先使用 int 和 double
javaint count = 10; // 而不是 byte 或 short double price = 9.99; // 而不是 float使用 var 类型推断(Java 10+)
javavar name = "Alice"; // 推断为 String var age = 25; // 推断为 int var list = new ArrayList<String>();使用下划线分隔大数字
javalong population = 1_400_000_000L; int million = 1_000_000;避免魔法数字
java// ❌ 不推荐 if (status == 1) { } // ✅ 推荐 final int STATUS_ACTIVE = 1; if (status == STATUS_ACTIVE) { }
🧭 类型选择清单
初学时不要为了“省内存”到处使用 byte、short、float。
常见选择:
text
整数计数:int。
大范围整数:long。
小数计算:double。
金额计算:BigDecimal。
真假条件:boolean。
单个字符:char。
文本:String。为什么金额不用 double?
java
double price = 0.1 + 0.2;
System.out.println(price); // 0.30000000000000004金额应该使用:
java
BigDecimal amount = new BigDecimal("0.30");注意使用字符串构造 BigDecimal,避免把 double 的误差带进去。
📖 默认值与局部变量
成员变量有默认值:
java
class User {
int age; // 默认 0
boolean vip; // 默认 false
String name; // 默认 null
}局部变量没有默认值,必须先赋值:
java
void test() {
int x;
// System.out.println(x); // 编译错误
x = 10;
System.out.println(x);
}这个规则能避免很多“读到随机值”的问题,也是 Java 比 C 更安全的地方之一。
🛠 初学排查清单
遇到类型相关错误时,按下面检查:
text
变量是否已经初始化。
long 字面量是否加 L。
float 字面量是否加 f。
整数除法是否需要转 double。
强制转换是否可能溢出。
字符串是否可能为 null。
浮点数是否用 == 比较。
char 运算是否被提升成 int。常用修复方式:
text
显式比较:x != 0。
显式类型转换:(double) a / b。
使用常量名替代魔法数字。
用 BigDecimal 表达金额。
引用类型使用前先判断是否为 null。✅ 掌握标准
学完本课后,应能做到:
text
能说出 8 种基本类型。
能区分基本类型和引用类型。
能解释自动转换和强制转换。
能识别整数除法、浮点误差、溢出问题。
能知道成员变量和局部变量默认值差异。
能选择 int、long、double、BigDecimal 的使用场景。
能说明 Java boolean 与 C 整数布尔的区别。变量和类型是 Java 的地基。后面所有集合、对象、泛型和并发,最终都建立在类型规则之上。
📝 练习预告
完成 练习/Ex01_Variables.java 中的6道题:
- 基础声明与赋值
- 类型转换
- 常量使用
- 表达式计算
- 类型陷阱识别
- 综合应用
完成后对比 答案/Sol01_Variables.java,查看详细讲解和多种解法。
🎓 下一步
- 第2课:运算符 - 算术、关系、逻辑、位运算
- 第3课:控制流 - if、switch、循环