首页 / Java 入门教程 / if-else 条件语句

Java 入门教程

if-else 条件语句

本教程共 100 篇 · 第 19 篇 · 更新于 2026-08-05 · 约 6 分钟阅读

JavaJava 入门教程if语句条件判断分支结构

19. if-else 条件语句

本节目标:掌握 if 的单分支、双分支、多分支三种写法,理解 else if 串联的判断顺序,避开边界、浮点比较、引用比较几个高频坑,能写出正确的条件判断代码。

程序最日常的需求就是”看情况办事”。Java 用 if 语句干这件事,它接收一个布尔值(truefalse)当条件,条件成立就执行后面花括号里的代码。

单分支:if

最朴素的形式只关心”满足时做什么”:

public class Main {
    public static void main(String[] args) {
        int n = 70;
        if (n >= 60) {
            System.out.println("及格了");
        }
        System.out.println("END");
    }
}
```bash

`n >= 60` 算出来是 `true`,所以打印"及格了",接着照常打印 `END`。把 `n` 改成 50 再跑,条件变 `false`,花括号里整段被跳过,只看到 `END`。

> [!WARNING]
> 有人图省事,if 只有一条语句时不写花括号:
> ```java
> if (n >= 60)
>     System.out.println("及格了");
>     System.out.println("恭喜你"); // 这行其实不在 if 里!
> ```
> 缩进会骗人。第二行永远会执行,跟 if 无关。新手和 git 自动合并都容易在这栽跟头,所以**一律写上花括号**

## 双分支:if-else

加上 `else`,条件不成立时走另一段:

```java
int n = 50;
if (n >= 60) {
    System.out.println("及格了");
} else {
    System.out.println("挂科了");
}

else 不是必须的,但加上它能覆盖”否则”的情况,逻辑更完整。

多分支:else if 串联

选项超过两个时,用 else if 串起来:

int n = 85;
if (n >= 90) {
    System.out.println("优秀");
} else if (n >= 60) {
    System.out.println("及格");
} else {
    System.out.println("挂科");
}
```bash

## 顺序决定结果,别写反

`else if` 是从上往下逐个判断的,一旦某个 `if` 命中,后面的分支整段跳过。所以**判断范围要从大到小排**

```java
// 错误写法:n=100 会先命中 n>=60,永远走不到"优秀"
if (n >= 60) { ... }
else if (n >= 90) { ... }

// 正确写法:大范围先判断
if (n >= 90) { ... }
else if (n >= 60) { ... }
else { ... }
Note

也可以反过来从小到大判断,用 n < 60n < 90 这样的上界。关键是保证各区间不重叠、不遗漏。

边界条件:> 和 >= 不一样

看一段常见的错:

int n = 90;
if (n > 90) {
    System.out.println("优秀");
} else if (n >= 60) {
    System.out.println("及格");
}
```bash

本想 90 分算优秀,结果 `>` 把 90 挡在门外,打印出"及格"。`>` 和 `>=` 差一个等号,含义天差地别,写判断时把边界值(比如正好 60、正好 90)在脑子里过一遍。

## 浮点数别用 == 比相等

计算机存小数有误差,`1 - 9.0/10` 算出来并不是精确的 0.1。直接用 `==` 比较多半失败:

```java
double x = 1 - 9.0 / 10;
if (Math.abs(x - 0.1) < 0.00001) {  // 看差值的绝对值够不够小
    System.out.println("x 约等于 0.1");
}

正确做法是比较”两者差的绝对值是否小于一个极小阈值”。

引用类型用 equals,不是 ==

比较两个字符串内容是否相同,要用 equals()

String s1 = "hello";
String s2 = "HELLO".toLowerCase();
if (s1.equals(s2)) {
    System.out.println("内容相同");
}
```bash

`==` 对引用类型比较的是"是不是同一个对象",不是"内容是否一样"。`s1 == s2` 这里会是 `false`,因为它们是两个不同的对象。

> [!WARNING]
> 如果 `s1` 是 `null`,`s1.equals("hello")` 会直接抛 `NullPointerException`。稳妥写法是把不为 null 的字面量放前面:`"hello".equals(s1)`,这样 s1 为 null 时也只会返回 false,不会崩。

## 嵌套 if

if 里面还能再套 if,处理"大条件里再分小条件"

```java
int age = 20;
boolean hasTicket = true;
if (age >= 18) {
    if (hasTicket) {
        System.out.println("可以入场");
    } else {
        System.out.println("请先买票");
    }
} else {
    System.out.println("未成年禁止入场");
}

嵌套能表达更细的逻辑,但层次别太深,三层以上就该想想是不是该拆成方法了。

悬垂 else:else 到底跟着谁

不写花括号时,嵌套 if 会出现一个经典歧义:

int age = 15;
boolean vip = false;
if (age >= 18)
    if (vip)
        System.out.println("VIP 入场");
else
    System.out.println("未成年禁止入场");   // 缩进在骗人
```bash

看缩进像是 `else` 配外层的 `if (age >= 18)`,实际编译器的规则是「**else 永远跟最近的、还没配对的 if**」——它配的是里层的 `if (vip)`。所以 `age = 15` 时这段什么都不打印。

修法只有一个:**每个 if / else 都写花括号**。花括号一加,谁跟谁配一目了然,编译器和你的理解就不会分家。

## 条件里的 &&|| 会短路

`else if` 链是从上往下一个个试,命中就停。单个条件内部的 `&&`、`||` 也有类似的「能不算就不算」行为,叫**短路求值**

- `A && B`:`A` 为 `false` 时,`B` 根本不执行,整体直接是 `false`。
- `A || B`:`A` 为 `true` 时,`B` 根本不执行,整体直接是 `true`。

这不只是性能优化,更是防崩的常用手法:

```java
String name = null;
if (name != null && name.length() > 3) {   // 顺序不能反
    System.out.println("名字够长");
}

name != nullfalse,后半段 name.length() 被短路掉,不会抛 NullPointerException。两个条件调换位置,程序立刻崩。

Warning

单个 &| 也能连布尔值,但它们不短路,两边都会算。上面的例子改成 name != null & name.length() > 3,照样抛空指针。日常判断一律用 &&||

动手练一练

写一个 checkGrade 的小逻辑:输入分数,90 以上打印”优秀”,60 到 89 打印”及格”,否则打印”不及格”。重点练 else if 的边界:想清楚 89 和 90 分别落哪边,再补一个”负数直接提示非法”的分支。

Tip

把边界值(0、59、60、89、90、100)逐个测一遍,是检验 if 边界是否写对的笨办法,也是最有效的办法。

易错提醒

最常见的两个坑:一是把 if (score = 60) 写成赋值(单等号),本意是比较却变成了赋值;二是多个 else if 顺序排反,比如先判断 >= 60 再判断 >= 90,导致 95 分也被前面的分支截走。范围判断要想清楚互斥关系。

第一个坑值得单独说说。C 语言里 if (score = 60) 能编译通过,赋值结果 60 被当成”真”,是著名的隐蔽 bug 来源。Java 把这条路堵死了——score = 60 的结果是 int,不是 boolean

error: incompatible types: int cannot be converted to boolean
        if (score = 60) {
                  ^
1 error
```java

但有个例外要当心:两边都是 `boolean` 时,编译器拦不住。

```java
boolean ok = false;
if (ok = true) {          // 这是赋值!ok 被改成 true,条件恒成立
    System.out.println("永远会进来");
}

这段能编译、能运行,还顺手把 ok 改掉了。判断布尔变量直接写 if (ok) 就行,别画蛇添足加 == true,也就不会手滑写成 =

小结

if 是条件判断的主力,else 覆盖否则情况,else if 串起多分支;顺序和边界是新手最容易翻车的地方;浮点别用 ==,引用比较用 equals 并防 null。把这几条记牢,判断逻辑基本就稳了。

拓展:组合条件与字符串比较

真实判断往往是”多条件叠加”。比如”成绩及格且出勤率达标”才算通过,用 &&(并且)连接;“是会员或者消费满额”享受折扣,用 ||(或者)连接。注意 Java 里逻辑运算符是 &&||,不是单 &/|(后者是位运算,行为不同且可能不短路)。

还有个高频坑:判断字符串内容相等,必须用 equals,不能写 ==== 比的是”是不是同一个对象”,equals 比的是”内容一不一样”。例如 input.equals("exit") 才是正确写法。Java 的布尔类型只有 true/false,没有”非零即真”那一套,所以 if (score) 这种写法在 Java 里直接编译报错。

常见疑问

Q:if 里能定义变量吗?

能,但它只在那对花括号里活着,出去就没了:

if (score >= 60) {
    String msg = "及格";
    System.out.println(msg);
}
// System.out.println(msg);   // 编译错误:msg 已出作用域
```java

要在 `if` 外面用,就把声明提到 `if` 之前。

**Q:条件很长很复杂,怎么写才不乱?**

抽成有名字的布尔变量,让代码自己解释自己:

```java
boolean adult    = age >= 18;
boolean paid     = balance >= price;
boolean inStock  = stock > 0;

if (adult && paid && inStock) {
    System.out.println("下单成功");
}

比一行塞五个条件好读得多,调试时还能单独打印每个变量看是哪一项没满足。

Q:三元运算符能替代 if-else 吗?

只在「二选一取个值」时能替代,比如 int max = a > b ? a : b;。分支里要执行多条语句,还是老实用 if-else。三元运算符也别嵌套,套两层就没人看得懂了。