Skip to content

第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. 整数类型

类型字节数取值范围默认值
byte1字节-128 ~ 1270
short2字节-32,768 ~ 32,7670
int4字节-2^31 ~ 2^31-10
long8字节-2^63 ~ 2^63-10L
java
byte age = 25;
short year = 2024;
int population = 1_400_000_000;  // 下划线分隔,增强可读性
long distance = 9_460_000_000_000L;  // 后缀 L 或 l

2. 浮点类型

类型字节数精度默认值
float4字节7位有效数字0.0f
double8字节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 自动提升为 int

2. 强制类型转换(显式转换)

规则:大范围 → 小范围,需要强制转换

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字节)
数组越界不检查(导致崩溃)运行时检查(抛异常)
类型转换隐式转换较多更严格,需显式转换
未初始化变量随机值成员变量有默认值,局部变量必须初始化

💡 最佳实践

  1. 优先使用 int 和 double

    java
    int count = 10;     // 而不是 byte 或 short
    double price = 9.99; // 而不是 float
  2. 使用 var 类型推断(Java 10+)

    java
    var name = "Alice";     // 推断为 String
    var age = 25;           // 推断为 int
    var list = new ArrayList<String>();
  3. 使用下划线分隔大数字

    java
    long population = 1_400_000_000L;
    int million = 1_000_000;
  4. 避免魔法数字

    java
    // ❌ 不推荐
    if (status == 1) { }
    
    // ✅ 推荐
    final int STATUS_ACTIVE = 1;
    if (status == STATUS_ACTIVE) { }

🧭 类型选择清单

初学时不要为了“省内存”到处使用 byteshortfloat

常见选择:

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道题:

  1. 基础声明与赋值
  2. 类型转换
  3. 常量使用
  4. 表达式计算
  5. 类型陷阱识别
  6. 综合应用

完成后对比 答案/Sol01_Variables.java,查看详细讲解和多种解法。


🎓 下一步

  • 第2课:运算符 - 算术、关系、逻辑、位运算
  • 第3课:控制流 - if、switch、循环