表达式与语句
本教程共 100 篇 · 第 16 篇 · 更新于 2026-08-05 · 约 5 分钟阅读
16. 表达式与语句
本节目标:分清「表达式」和「语句」这两个基础概念,知道哪些表达式能直接当语句用,并理解花括号
{ }组成的「块」在 Java 里的通用地位。
表达式:算出一个值
表达式是由变量、运算符、方法调用按语法拼起来的东西,它会算出单个值。
下面加粗的都是表达式:
int cadence = 0;
int result = 1 + 2; // 1 + 2 是表达式,算出 3
System.out.println("hi " + cadence); // "hi " + cadence 是表达式
if (result == 3) { } // result == 3 是表达式,算出 boolean
```java
表达式算出的值是什么类型,取决于它用了什么。上面这几个分别算出了 `int`、`String`、`boolean`。
表达式还能**套表达式**,组成复合表达式:
```java
int x = 5, y = 10;
int z = x + y / 100; // y/100 是子表达式,再和 x 相加
Tip复合表达式里顺序不明确时,用括号钉死。比如
(x + y) / 100和x + y / 100完全不同。这点在上一章优先级里详细讲过,括号既保正确又保清晰。
方法调用本身也是表达式
带返回值的方法调用,本身就是一个表达式,因为它也算出了值:
int m = Math.max(3, 5); // Math.max(3, 5) 是表达式,算出 5
System.out.println(Math.max(3, 5)); // 表达式直接嵌进 println
```bash
所以「方法调用能当语句」和「方法调用是表达式」两句话都对:有返回值时它算出了值(是表达式),加个分号它就成了完整指令(是语句)。无返回值的方法(`void`)只能当语句,不能塞进需要值的地方。
## 声明语句的初始化是可选的
声明语句不一定要当场给初值,可以先声明、后用:
```java
int total; // 只声明,未初始化
total = compute(); // 之后赋值
但前面提过,局部变量声明后若一直不赋值就使用,编译器会报错。声明和可执行赋值在「时机」上可以分开,在「使用前必须赋值」这条上从不放松。
语句:以分号结尾的一句完整指令
语句是程序里一个完整的执行单元,相当于自然语言的一个句子。大部分语句以分号 ; 结尾。
有几类表达式,后面加个分号就能直接变成语句,叫表达式语句:
aValue = 8933.234; // 赋值语句
aValue++; // 自增语句
System.out.println("Hello"); // 方法调用语句
Bicycle myBike = new Bicycle(); // 对象创建语句
```java
除了表达式语句,还有两类:
**声明语句**——声明一个变量:
```java
double price = 9.9; // 既是声明,也带赋值
int count; // 只声明
控制流语句——控制代码执行顺序的,比如 if、for、while。这些留到后面专门的流程控制章节讲,本章先知道它们也属于语句即可。
块:用花括号打包
块(block) 是用一对花括号 { } 包起来的零条或多条语句。它看起来像这样:
{
int temp = 1;
System.out.println(temp);
}
```java
块的关键能力:**任何需要「一条语句」的地方,都可以用一个块顶上。** 比如 `if` 后面正常跟一条语句,但你经常想执行好几条,那就用块包起来:
```java
if (score > 60) { // 这里用了块,而不是单条语句
System.out.println("及格");
System.out.println("继续加油");
}
即便只有一条语句,很多人也习惯用花括号包起来——这样以后要加语句时不容易漏写括号,也更统一。
Note块也定义了变量的作用域。在块里声明的变量,出了这个块就访问不到(第 12 章提过作用域)。所以块不只是「打包」,还顺带框定了变量的生命范围。
三者怎么摆在一起
把表达式、语句、块的关系串成一个完整例子:
public class Demo {
public static void main(String[] args) {
int a = 3;
int b = 4;
int sum = a + b; // a + b 是表达式;整行是声明+赋值语句
System.out.println(sum); // 方法调用表达式 + 分号 = 语句
if (sum > 0) { // 控制流语句,后面跟一个块
System.out.println("正数");
}
}
}
```bash
读这段代码时,脑子里可以分层:最里层是表达式算值,往上是语句执行动作,再往上是块把动作组织成逻辑段落。
## 哪些表达式不能直接当语句
前面说「有几类表达式加个分号就能变语句」。反过来说,**不是所有表达式都能直接当语句**。
比如下面这两行,在 Java 里都是**非法**的:
```java
int a = 1, b = 2;
// a + b; // 报错:a + b 算出了值,但没人接收,毫无意义
// a > b; // 报错:同理
Java 规定,能独立成「表达式语句」的只有四种:赋值、自增自减、++/--、方法调用、对象创建。像 a + b 这种「算完就扔」的表达式,不能单独占一行,必须把它赋给变量、或放进 if/while 等需要值的地方。
int x = a + b; 之所以合法,是因为它是声明 + 赋值语句,不是「裸」的表达式语句。
空语句:一个单独的分号
只有一个分号、什么都没有,叫空语句。它合法,但一般没用:
; // 空语句,啥也不做
```java
偶尔在循环里见到,比如 `for (;;) ;` 这种死循环占位。日常写代码基本用不到,知道有这东西、别不小心多敲个分号就行——比如在 `if` 后面误加空语句,会让逻辑悄悄跑偏:
```java
if (score > 60);
System.out.println("及格"); // 这行不受 if 控制!因为上面的分号已经结束 if
那个分号让 if 体变成了空语句,println 永远会执行。这是个隐蔽的经典 bug。
块可以嵌套
块里面还能再套块,每一层都有自己的作用域:
{
int x = 1;
{
int y = 2; // y 只在内层块可见
System.out.println(x + y);
}
// System.out.println(y); // 报错:y 已超出作用域
}
```bash
嵌套块在复杂逻辑里很常见。理解「内层能看外层的变量,外层看不到内层的」,作用域就不乱了。
## 小结
表达式算出单个值,由变量、运算符、方法调用组成,可嵌套。
语句是以分号结尾的完整执行单元:表达式语句(赋值、`++/--`、方法调用、对象创建)、声明语句、控制流语句。
块用 `{ }` 把多条语句打包,可在任何需要单条语句处使用,并界定变量作用域。注意只有赋值、自增、方法调用、对象创建能单独成语句,`if` 后误加分号是常见 bug。