语法基础
概要
Java 是静态类型语言,变量必须先声明类型。数据类型分基本类型和引用类型两种,本章涵盖从类型、运算符到方法和集合的核心语法。
一、数据类型
Java 中的数据类型可分为 2 种:
1. 基本数据类型
基本数据类型包括 boolean、char、byte、short、int、long、float 和 double 共 8 种。不同的数据类型有着不同的取值范围和内存占用大小。这些类型由 JVM 直接管理,存储在栈(Stack)内存中,效率极高。
整数和小数取值范围大小关系:double > float > long > int > short > byte
| 分类 | 关键字 | 位数 (bit) | 字节 (Byte) | 取值范围 | 默认值 | 快速记忆 |
|---|---|---|---|---|---|---|
| 整数 | byte | 8 | 1 | -128 ~ 127 | 0 | 极小整数 |
| short | 16 | 2 | -32,768 ~ 32,767 | 0 | 短整数 | |
| int | 32 | 4 | 约 ±21亿 (2³¹−1) | 0 | 默认整数类型 | |
| long | 64 | 8 | 约 ±9×10¹⁸ (2⁶³−1) | 0L | 大数据 / 时间戳 | |
| 浮点 | float | 32 | 4 | ±3.4E38 (有效位数 6~7 位) | 0.0f | 单精度 |
| double | 64 | 8 | ±1.7E308 (有效位数 15 位) | 0.0d | 默认浮点类型 | |
| 字符 | char | 16 | 2 | 0 ~ 65,535 (Unicode) | '�' | 单个文字 / 符号 |
| 布尔 | boolean | JVM 依赖 | JVM 依赖 | true / false | false | 逻辑判断 |
💡 核心要点补充
后缀要求:
- long:赋值时必须加 L(如
long num = 100L;)。 - float:赋值时必须加 F(如
float f = 3.14F;),否则会被当作 double 处理导致编译报错。
Boolean 占用空间:在 JVM 规范中,单个 boolean 变量在编译后使用 int 代替(4字节),而 boolean 数组则会被编译成 byte 数组(1字节)。
精度损耗
float 和 double 采用的是 IEEE 754 标准,不能用于精确的货币计算(会出现 0.1 + 0.2 != 0.3 的情况)。精确计算请使用 java.math.BigDecimal。
2. 引用数据类型
引用类型存储的是对象的地址(指向堆内存),而非值本身。常见的有 String、数组、类和接口。所有引用类型的默认值都是 null。
// 字面量:检查串池,存在则复用
String name = "java";
// new:在堆中创建新对象
String a = new String("java");
char[] chs = {'j', 'a', 'v', 'a'};
String b = new String(chs);
// 内容比较用 equals(),== 比较的是地址
String s1 = "abc", s2 = "Abc";
System.out.println(s1.equals(s2)); // false
System.out.println(s1.equalsIgnoreCase(s2)); // trueStringBuilder sb = new StringBuilder("Zm");
sb.append("zzzzz"); // 拼接
sb.reverse(); // 反转
String str = sb.toString(); // 转回 Stringimport java.util.StringJoiner;
StringJoiner sj = new StringJoiner("---");
sj.add("aa").add("bb").add("cc");
System.out.println(sj); // aa---bb---cc
StringJoiner sj2 = new StringJoiner(", ", "[", "]");
sj2.add("x").add("y");
System.out.println(sj2); // [x, y]判等方式: == 比较内存地址,equals() 比较字符串内容。
| 场景 | 推荐工具 |
|---|---|
| 固定字符串 | String |
| 循环中大量拼接或反转 | StringBuilder |
拼接列表并加前后缀(如 [x, y]) | StringJoiner |
二、运算符
在 Java 中,运算不仅仅是算结果,还涉及类型转换。
- 隐式转换:取值范围小的和大的运算,小会自动提升为大的再计算。
- 特殊规则:byte、short、char 运算时,一律先提升为 int。
- 强制转换:大容量转小容量必须手动强转:
(目标类型) 值。
byte a = 10;
int b = 20;
int c = a + b; // byte 自动提升为 int
byte x = 5, y = 10;
int z = x + y; // byte/short/char 运算 → int
byte sum = (byte)(x + y); // 强制转换
// int + double → 自动提升为 double
double d = 10 + 3.14;三、判断和循环
条件判断和循环是程序的基本控制结构。判断用 if/switch 控制分支,循环用 for/while/do...while 重复执行代码块。
| 循环类型 | 最佳使用场景 | 核心特点 |
|---|---|---|
| for | 已知循环次数 | 初始化、条件、迭代集中在一起,结构紧凑 |
| while | 未知循环次数 | 先判断后执行,可能一次都不执行 |
| do...while | 至少执行一次 | 先执行一次循环体,再判断条件 |
| 增强 for | 遍历集合/数组 | 无需索引,语法最简洁 |
/** if语句 */
if (flag) {}
/** switch语句 */
switch (flag) {
case 'xx':
break;
default:
break;
}
// JDK 14+ 箭头语法
switch (flag) {
case 1 -> {}
default -> {}
}/** 标准 for */
for (int i = 0; i < 5; i++) {
if (i == 3) {
continue; // 跳过本次循环
}
System.out.println(i);
}
/** 循环标号——跳出外层循环 */
outer:
for (int i = 0; i < 5; i++) {
for (int j = 0; j < 5; j++) {
if (j == 2) break outer;
}
}
/** 增强 for——遍历集合 */
for (String s : List.of("A", "B", "C")) {
System.out.println(s);
}/** while——先判断后执行 */
int i = 0;
while (i < 3) {
System.out.println(i);
i++;
}
/** do...while——先执行一次再判断 */
int j = 0;
do {
System.out.println(j);
j++;
} while (j < 3);四、数组
数组是存储同种数据类型、固定长度的连续空间。存储时需考虑隐式转换:小类型可存入大类型数组,反之不行(如 int 数组可存 byte/short/int,不能存 double/boolean)。
| 方式 | 语法示例 | 适用场景 |
|---|---|---|
| 静态初始化 | int[] arr = {1, 2, 3}; | 已知具体数据内容 |
| 动态初始化 | int[] arr = new int[5]; | 只知长度,数据后续动态存入 |
import java.util.Arrays;
int[] arr1 = {11, 12, 13};
String[] arr2 = {"张三", "李斯"};
double[] arr3 = {1.93, 1.78};
System.out.println(arr1[2]);
System.out.println(Arrays.toString(arr1));
// 标准 for:需要索引时使用
for (int i = 0; i < arr1.length; i++) {
System.out.println("索引 " + i + ": " + arr1[i]);
}
// 增强 for:仅需取值时更简洁
for (int val : arr1) {
System.out.println(val);
}String[] arr = new String[10];
arr[0] = "张三";
// 数组默认初始化值规律
// 整数类型:默认初始化值 0
// 小数类型:默认初始化值 0.0
// 字符类型:默认初始化值 '�' 空格
// 布尔类型:默认初始化值 false
// 引用数据类型:默认初始化值 null五、集合
ArrayList 是 Java 最常用的动态集合,长度可变。集合只能存储引用类型——基本类型需用包装类(int → Integer,char → Character)。
import java.util.ArrayList;
public class Main {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
// 增
list.add("zeming");
list.add("bbb");
// 删
list.remove(1);
// 改
list.set(0, "哥哥");
// 查
String item = list.get(0);
int size = list.size();
System.out.println(list);
}
}| 操作 | 方法 | 说明 |
|---|---|---|
| 增 | add(E e) / add(int i, E e) | 末尾追加 / 指定位置插入 |
| 删 | remove(int i) / remove(Object o) | 按索引删除 / 按元素删除 |
| 改 | set(int i, E e) | 替换指定位置元素 |
| 查 | get(int i) | 按索引获取 |
| 长度 | size() | 返回元素个数 |
六、方法
方法(Method)是组织可复用代码的基本单元,定义一次,多处调用。基本类型传值,引用类型传地址——在方法内修改引用类型(如数组)会影响原对象。
public static void playGame() {
System.out.println("开始游戏");
}
// 调用
playGame();public static void playGame(String name, int age) {
System.out.println(name + ",年龄:" + age);
}
// 调用
playGame("张三", 25);public static int getSum(int a, int b, int c) {
return a + b + c;
}
// 调用
int sum = getSum(1, 2, 3);
// 返回数组
public static int[] copy(int[] arr, int from, int to) {
int[] temp = new int[to - from];
return temp;
}小结
| 知识点 | 重点强调 | 容易忽视的 Bug |
|---|---|---|
| 数据类型 | long 加 L,float 加 F;String 用 equals() 比较内容 | 丢失后缀编译报错;用 == 比较字符串 |
| 判断和循环 | switch 每个 case 必须 break(或使用箭头语法);continue 跳过当次、break 终止循环 | continue 后写 break(永远不会执行) |
| 数组 | 长度固定,索引从 0 开始 | ArrayIndexOutOfBoundsException 越界 |
| 集合 | ArrayList 长度可变;基本类型需用包装类(int → Integer) | 取元素时忘记类型转换 |
| 方法 | 基本类型传值,引用类型传地址 | 方法内改数组/对象会影响外部原值 |
📖 相关资源
- Java 教程 - Java 基础语法教程