当前位置:首页 > 技术 > 正文内容

程序控制流程:顺序与分支结构

访客 技术 2026年6月23日 1

5.1 顺序与分支结构

5.1.1 顺序结构

顺序结构是程序设计中最基础的控制方式,它按照代码语句的书写顺序逐条执行,直到程序运行结束。这种结构简单直观,是所有复杂程序的基础组成部分。

顺序结构示例:

public class FirstProgram {
    public static void main(String[] args) {
        System.out.println("欢迎学习Java编程!");
    }
}

在上述代码中,仅包含一条输出语句,系统会按照从上到下的顺序依次执行该语句,输出"欢迎学习Java编程!"。

5.1.2 分支结构

分支结构也称为选择结构,它根据指定条件表达式的计算结果来选择不同的程序执行路径。Java语言提供了两种实现分支结构的语句:if条件语句和switch多分支语句。

5.1.2.1 if条件语句

if语句通过判断条件的真假来决定是否执行特定的代码块。根据复杂程度的不同,if语句可以分为单分支、双分支和多分支三种形式。

1.单分支结构

if (条件表达式) {
    // 条件成立时执行的代码块
}

示例:

int temperature = 25;
if (temperature > 30) {
    System.out.println("今天气温很高");
}
System.out.println("程序执行完毕");

2.双分支结构

if (条件表达式) {
    // 条件成立时执行的代码块
} else {
    // 条件不成立时执行的代码块
}

示例:

int score = 85;
if (score >= 60) {
    System.out.println("考试成绩合格");
} else {
    System.out.println("考试成绩不合格");
}
System.out.println("程序执行完毕");

3.多分支结构

if (条件表达式1) {
    // 条件1成立时执行的代码块
} else if (条件表达式2) {
    // 条件2成立时执行的代码块
} else if (条件表达式3) {
    // 条件3成立时执行的代码块
} else {
    // 所有条件都不成立时执行的代码块
}

示例:

int month = 5;
if (month >= 3 && month <= 5) {
    System.out.println("春季");
} else if (month >= 6 && month <= 8) {
    System.out.println("夏季");
} else if (month >= 9 && month <= 11) {
    System.out.println("秋季");
} else {
    System.out.println("冬季");
}
System.out.println("程序执行完毕");

多分支结构的典型应用场景之一是求解一元二次方程。一元二次方程的标准形式为:ax² + bx + c = 0,其中a、b、c为实数常数,且a≠0。根据判别式Δ = b² - 4ac的值,可以判断方程根的情况:

import java.util.Scanner;
import java.lang.Math;

public class QuadraticEquation {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        System.out.print("请输入系数a:");
        double coefficientA = scanner.nextDouble();
        System.out.print("请输入系数b:");
        double coefficientB = scanner.nextDouble();
        System.out.print("请输入系数c:");
        double coefficientC = scanner.nextDouble();

        double discriminant = coefficientB * coefficientB - 4 * coefficientA * coefficientC;
        
        if (discriminant > 0) {
            double root1 = (-coefficientB + Math.sqrt(discriminant)) / (2 * coefficientA);
            double root2 = (-coefficientB - Math.sqrt(discriminant)) / (2 * coefficientA);
            System.out.println("方程有两个不相等的实数根:");
            System.out.println("x1 = " + root1);
            System.out.println("x2 = " + root2);
        } else if (discriminant == 0) {
            double root = -coefficientB / (2 * coefficientA);
            System.out.println("方程有两个相等的实数根:");
            System.out.println("x = " + root);
        } else {
            double realPart = -coefficientB / (2 * coefficientA);
            double imaginaryPart = Math.sqrt(Math.abs(discriminant)) / (2 * coefficientA);
            System.out.println("方程有两个共轭复根:");
            System.out.println("x1 = " + realPart + " + " + imaginaryPart + "i");
            System.out.println("x2 = " + realPart + " - " + imaginaryPart + "i");
        }
        scanner.close();
    }
}

注意事项:

if (1.0 / 1000000 == 0.0) {
    System.out.println("极小值被视为零");
}
// 由于浮点数精度问题,上述比较可能产生意外结果

5.1.2.2 嵌套if语句

嵌套if语句是在if或else分支中再次包含完整的if-else结构,用于处理更复杂的条件判断。

基本格式:

if (条件1) {
    if (条件2) {
        // 条件1和条件2都满足时执行的代码
    } else {
        // 条件1满足但条件2不满足时执行的代码
    }
} else {
    // 条件1不满足时执行的代码
}

示例:

int valueX = 8;
int valueY = -2;

if (valueX > 0) {
    if (valueY > 0) {
        System.out.println("X和Y都是正数");
    } else {
        System.out.println("X是正数,Y是负数");
    }
} else {
    System.out.println("X不是正数");
}

嵌套if语句可以有多层嵌套,但嵌套层数不宜过多,否则会导致程序结构复杂、难以理解和维护。建议将复杂的条件判断重构为更清晰的逻辑结构。

5.1.3 switch多分支语句

1.switch语句的基本语法

switch语句根据表达式的值从多个可能的代码块中选择其中一个执行。其语法格式如下:

switch (表达式) {
    case 常量1:
        // 表达式值等于常量1时执行的代码
        break;
    case 常量2:
        // 表达式值等于常量2时执行的代码
        break;
    // ... 更多case分支
    default:
        // 表达式值与所有case常量都不匹配时执行的代码
}

示例:

import java.util.Scanner;

public class DaySelector {
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        System.out.println("请输入数字(1-7):");
        int dayNumber = input.nextInt();
        
        switch (dayNumber) {
            case 1:
                System.out.println("星期一");
                break;
            case 2:
                System.out.println("星期二");
                break;
            case 3:
                System.out.println("星期三");
                break;
            case 4:
                System.out.println("星期四");
                break;
            case 5:
                System.out.println("星期五");
                break;
            case 6:
                System.out.println("星期六");
                break;
            case 7:
                System.out.println("星期日");
                break;
            default:
                System.out.println("输入无效,请输入1-7之间的数字");
                break;
        }
        input.close();
    }
}

执行流程说明:

  1. 首先创建Scanner对象读取用户输入
  2. 计算switch表达式的值
  3. 将表达式的值与各case后的常量逐一比较
  4. 找到匹配的case后执行相应代码块
  5. 遇到break语句时跳出switch结构
  6. 若无匹配case,则执行default分支(如果存在)
  7. 释放Scanner资源

语法特点:

  • 表达式支持byte、short、int、char、String等类型
  • case后的常量值必须唯一,不能重复
  • break语句用于终止switch执行,防止case穿透
  • case和default的顺序可以灵活调整,建议将default放在最后
  • default分支是可选的
  • 每个case分支可以包含任意合法Java语句
  • switch结构可以用if-else完全实现,但在多分支场景下switch更简洁清晰

典型应用 - 成绩等级评定:

import java.util.Scanner;

public class GradeEvaluator {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        System.out.print("请输入学生成绩:");
        int studentScore = scanner.nextInt();
        
        switch (studentScore / 10) {
            case 10:
            case 9:
                System.out.println("优秀");
                break;
            case 8:
                System.out.println("良好");
                break;
            case 7:
                System.out.println("中等");
                break;
            case 6:
                System.out.println("及格");
                break;
            default:
                System.out.println("需要努力");
                break;
        }
        scanner.close();
    }
}

2.switch语句的嵌套使用

switch语句内部可以再次嵌套switch语句,用于处理更复杂的多层分支情况:

import java.util.Scanner;

public class ScholarshipEvaluator {
    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);
        System.out.print("请输入学生成绩:");
        int score = scan.nextInt();
        
        switch (score / 10) {
            case 10:
            case 9:
                System.out.println("评级:优秀");
                switch (score) {
                    case 100:
                        System.out.println("奖励:平板电脑");
                        break;
                    case 99:
                    case 98:
                    case 97:
                    case 96:
                    case 95:
                        System.out.println("奖励:智能手机");
                        break;
                    default:
                        System.out.println("奖励:学习用品");
                        break;
                }
                break;
            case 8:
                System.out.println("评级:良好");
                System.out.println("奖励:笔记本");
                break;
            case 7:
                System.out.println("评级:中等");
                break;
            case 6:
                System.out.println("评级:及格");
                break;
            default:
                System.out.println("评级:需要改进");
                break;
        }
        scan.close();
    }
}

3.Java 12至17版本switch语句新特性

(1)Java 12引入的箭头语法

Java 12为switch语句引入了箭头操作符(->)替代传统的冒号(:)语法。使用箭头语法时,case分支不会出现"fall-through"(穿透)现象,无需显式编写break语句,使代码更加简洁可靠。

// 使用Java 12新语法重写成绩评定
switch (score) {
    case 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100 -> System.out.println("奖励:平板电脑");
    case 80, 81, 82, 83, 84, 85, 86, 87, 88, 89 -> System.out.println("奖励:智能手机");
    default -> System.out.println("继续努力");
}

传统写法对比:

public static String getDayType(String day) {
    String result;
    switch (day) {
        case "MONDAY":
        case "TUESDAY":
        case "WEDNESDAY":
        case "THURSDAY":
        case "FRIDAY":
            result = "工作日";
            break;
        case "SATURDAY":
        case "SUNDAY":
            result = "周末";
            break;
        default:
            result = "未知";
            break;
    }
    return result;
}

Java 12+ 简化写法:

public static String getDayType(String day) {
    return switch (day) {
        case "MONDAY", "TUESDAY", "WEDNESDAY", "THURSDAY", "FRIDAY" -> "工作日";
        case "SATURDAY", "SUNDAY" -> "周末";
        default -> "未知";
    };
}

使用示例:

getDayType("MONDAY");    // 返回:工作日
getDayType("FRIDAY");    // 返回:工作日
getDayType("SATURDAY");  // 返回:周末

新语法的主要改进:

  • switch可以作为表达式使用,支持返回值
  • 使用箭头语法自动防止case穿透,无需break
  • 支持单case分支匹配多个值,用逗号分隔
  • 代码更加简洁易读

Java 12引入switch表达式主要解决了传统switch的两个问题:

  • case穿透问题:传统switch在缺少break时会自动执行下一个case,可能导致难以发现的逻辑错误
  • 代码冗余:每个case需要重复相似的代码结构

(2)Java 13引入的yield关键字

Java 13在switch表达式中引入了yield关键字,用于在多分支结构中返回值。当需要处理更复杂的逻辑时,可以使用yield返回结果:

public static String getDayType(String day) {
    return switch (day) {
        case "MONDAY", "TUESDAY", "WEDNESDAY", "THURSDAY", "FRIDAY" -> "工作日";
        case "SATURDAY", "SUNDAY" -> "周末";
        default -> {
            if (day == null || day.isEmpty()) {
                yield "输入为空";
            } else {
                yield "无效日期";
            }
        }
    };
}

使用示例:

getDayType("MONDAY");    // 工作日
getDayType("SATURDAY");  // 周末
getDayType("");          // 输入为空
getDayType("FREDAY");    // 无效日期

(3)Java 17引入的模式匹配

Java 17将模式匹配应用于switch表达式,使得处理不同数据类型更加灵活强大。switch模式匹配支持:类型模式、空模式、守卫模式和常量模式。

类型模式

传统方式处理多种类型需要大量的if-else判断:

public void processData() {
    Object[] dataItems = { "消息内容", 256, "标题", "Java", 2.718, "学习资料" };
    for (Object item : dataItems) {
        if (item instanceof Integer intValue) {
            System.out.println("整数类型:" + intValue);
        } else if (item instanceof Float floatValue) {
            System.out.println("浮点类型:" + floatValue);
        } else if (item instanceof Double doubleValue) {
            System.out.println("双精度类型:" + doubleValue);
        } else if (item instanceof String strValue) {
            System.out.println("字符串类型:" + strValue);
        } else {
            System.out.println("其他类型:" + item);
        }
    }
}

使用Java 17模式匹配的switch表达式重构:

public void processData() {
    Object[] dataItems = { "消息内容", 256, "标题", "Java", 2.718, "学习资料" };
    for (Object item : dataItems) {
        switch (item) {
            case Integer intValue -> System.out.println("整数类型:" + intValue);
            case Float floatValue -> System.out.println("浮点类型:" + floatValue);
            case Double doubleValue -> System.out.println("双精度类型:" + doubleValue);
            case String strValue -> System.out.println("字符串类型:" + strValue);
            default -> System.out.println("其他类型:" + item);
        }
    }
}

Java 17之前,switch表达式仅支持byte、short、char、int等整型类型及其包装类、String和枚举类型。引入类型模式后,switch表达式可以处理任意数据类型。

空模式

Java 17之前,向switch传递null会导致NullPointerException。现在可以通过case null直接处理空值:

public void processData() {
    Object[] dataItems = { "消息内容", 256, null, "Java" };
    for (Object item : dataItems) {
        switch (item) {
            case Integer intValue -> System.out.println("整数类型:" + intValue);
            case String strValue -> System.out.println("字符串类型:" + strValue);
            case null -> System.out.println("空值");
            default -> System.out.println("其他类型:" + item);
        }
    }
}

守卫模式

守卫模式允许在case标签后添加额外判断条件,只有类型匹配且条件为真时才执行该分支:

public void analyzeStrings() {
    Object[] dataItems = { "hello", "world", "java", "programming", "hi" };
    for (Object item : dataItems) {
        switch (item) {
            case Integer intValue -> System.out.println("整数类型:" + intValue);
            case String strValue && strValue.length() > 5 -> 
                System.out.println("长字符串:" + strValue);
            case String strValue -> 
                System.out.println("短字符串:" + strValue);
            case null -> System.out.println("空值");
            default -> System.out.println("其他类型:" + item);
        }
    }
}

守卫模式使代码更加灵活和富有表现力,能够在单个case中处理复杂的条件判断。

返回列表

上一篇:Spring事务同步机制详解与实战应用

没有最新的文章了...

相关文章

Linux crontab 详解

1) crontab 是什么cron 是 Linux 的定时任务守护进程;crontab 是用来编辑/查看“按时间周期执行命令”的表(cron table)。常见两类:用户 crontab:每个用户一份(crontab -e 编辑)系统级 crontab / cron.d:可指定执行用户(/etc/crontab、/etc/cron.d/*)2) crontab 时间...

富文本里可以允许的 HTML 属性

一、所有标签默认允许的安全属性(极少)class        (可选)id           (通常建议禁用)title️ 注意:id 容易被滥用做锚点注入,很多系统直接禁用class 允许的话最好只允许固定前缀(如 editor-*)二、a 标签允许属性<a href="" t...

Mac 安装 Node.js 指南

方法一:通过官网安装包(最简单,适合初学者)如果你只是想快速安装并开始使用,这是最直接的方法。访问 Node.js 官网。页面会显示两个版本:LTS (Recommended For Most Users):长期支持版,最稳定。建议选这个。Current:最新特性版,包含最新功能但可能不够稳定。下载 .pkg 安装包并运行。按照安装向导点击“下一步”即可完成。方法二:使用 Homebrew 安装(...

Dom\HTML_NO_DEFAULT_NS 的副作用:自动加闭合标签

在使用Dom\HTMLDocument时,Dom\HTML_NO_DEFAULT_NS 将禁止在解析过程中设置元素的命名空间, 此设置是为了与DOMDocument向后兼容而存在的。当使用它时,已知的一个副作用就是:自动加闭合标签例如 </img> 为什么会这样?当你使用:Dom\HTML_NO_DEFAULT_NS文档会变成 无命名空间模式,此时内部更接近 XML...

Laravel 事件和监听器创建

在 Laravel 中,使用 Artisan 命令创建 Events(事件) 和 Listeners(监听器) 是非常高效的。你可以通过以下几种方式来实现:1. 手动创建单个 Event如果你只想创建一个事件类,可以使用 make:event 命令:Bashphp artisan make:event UserRegistered执行后,文件将生成在 app/Even...

自定义域名解析神器 dnsmasq

什么是 dnsmasq?dnsmasq 是一个轻量级、功能强大的网络服务工具,专为小型和中等规模网络设计。它是一个综合的网络基础设施解决方案[1]。dnsmasq 能做什么?功能说明应用场景DNS 转发与缓存将 DNS 查询转发到上游服务器(ISP、Google DNS 等),并在本地缓存结果加快 DNS 查询速度,减少外部 DNS 流量本地 DNS解析本地网络设备的主机名,无需编辑&n...

发表评论

访客

◎欢迎参与讨论,请在这里发表您的看法和观点。