• 博客园logo
  • 会员
  • 周边
  • 新闻
  • 博问
  • 闪存
  • 众包
  • 赞助商
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
安绍峰
独学而无友,则孤陋而寡闻。
博客园    首页    新随笔    联系   管理    订阅  订阅
第5周 5.1 顺序与选择结构

5.1 顺序与选择结构


5.1.1 顺序结构

顺序结构是程序中最简单、最基本的流程控制结构,它按照程序中语句出现的先后顺序依次执行,直到程序的结束。
顺序结构示例:

   public class HelloWorld {
        public static void main(String[] args) {
            System.out.println("Hello, World!");
        }
    }

  //上述程序中,只有一条语句`System.out.println("Hello, World!");`,它按照顺序执行,输出"Hello, World!"。

5.1.2 选择结构

选择结构又叫分支结构,是根据条件表达式的值来决定程序的执行路径。Java语言提供了两种选择结构:if语句和switch语句。


5.1.2.1 if语句

if语句用于根据条件的真假来决定程序的执行路径。if语句有三种形式:if语句、if-else语句和if-else if-else语句。

if语句:if语句用于根据条件表达式的值来决定是否执行某段代码。如果条件表达式的值为true,则执行if语句块中的代码;如果条件表达式的值为false,则不执行if语句块中的代码。


1.单分支结构

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

示例:

int num = 10;
if (num > 0) {
    System.out.println("num是正数");
}
System.out.println("程序结束");

2.双分支结构

if (条件表达式) {
    // 条件为真时执行的代码块
} else {
    // 条件为假时执行的代码块
}

示例:

int num = 10;
if (num > 0) {
    System.out.println("num是正数");
} 
else {
    System.out.println("num是负数");
}
System.out.println("程序结束");


3.多分支结构

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

示例:

int num = 10;
if (num > 0) {
    System.out.println("num是正数");
} 
else if (num < 0) {
    System.out.println("num是负数");
} 
else {
    System.out.println("num是零");
}
System.out.println("程序结束");

多分支结构典型应用,求一元二次方程的根。中国古代数学家秦九韶提出了“秦九韶算法”,该算法可以用来求解一元二次方程。一元二次方程的一般形式为:ax2+bx+c=0,其中a、b、c为常数,且a≠0。根据判别式b2-4ac的值,可以判断方程的根的情况:

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

Scanner input = new Scanner(System.in);
        System.out.print("请输入a的值:");
        double a = input.nextDouble();
        System.out.print("请输入b的值:");
        double b = input.nextDouble();
        System.out.print("请输入c的值:");
        double c = input.nextDouble();

        double delta = b * b - 4 * a * c;
        if (delta > 0.0) {
            double x1 = (-b + Math.sqrt(delta)) / (2 * a);
            double x2 = (-b - Math.sqrt(delta)) / (2 * a);
            System.out.println("方程有两个实根:x1=" + x1 + ",x2=" + x2);
        } else if (delta == 0.0) {
            double x = -b / (2 * a);
            System.out.println("方程有一个实根:x=" + x);
        } else {
            double realPart = -b / (2 * a); // 实部
            double q=Math.sqrt(Math.abs(delta) / (2 * a) ;//虚部
            System.out.println("方程有两个虚根:x1=" + realPart + "+" + q + "i,x2=" + realPart + "-" + q + "i");
        }

image.png

if(1/(10^6)==0.0){
    System.out.println("1/(10^6)等于0");
}
//1/(10^6)等于0

5.1.2.2 嵌套if语句

格式:

if(条件1){
    if(条件2){
        //当条件1和条件2同时为真时执行
    }else{
        //当条件1为真,条件2为假时执行
    }
}else{
    //当条件1为假时执行
}

示例:

例如:


```Java
int a=2;
int b=-3;
if(a>0){
    if(b>0){
        System.out.println("a和b都是正数");
    }else{
        System.out.println("a是正数,b是负数");
    }
}else{
    System.out.println("a是负数");
}

image.png



```Java
if……else语句的嵌套可以有很多层,但要注意嵌套的层次不宜过多,否则会使程序的结构变得复杂,难以阅读和维护。
***

5.1.3 switch语句

1.switch语句的基本格式

switch语句用于根据表达式的值选择多个代码块中的一个执行,其格式如下:

switch(表达式){
    case 常量1:
        //当表达式的值等于常量1时执行的代码
        break;
    case 常量2:
        //当表达式的值等于常量2时执行的代码
        break;
    ...
    default:    //当表达式的值与所有case后面的常量都不相等时执行的代码
}

示例:

import java.util.Scanner;
        Scanner input = new Scanner(System.in);
        System.out.println("请输入a的值:");
        int a = input.nextInt();
switch(a){
    
    case 1:
        System.out.println("a的值为1");
        break;
    case 2:
        System.out.println("a的值为2");
        break;
    case 3:
        System.out.println("a的值为3");
        break;
       // default:
       // System.out.println("a的值不是1、2、3");
    
}
  • 1.程序执行过程:
  1. 首先创建一个Scanner对象,用于从控制台读取用户输入的整数。
  2. 然后使用switch语句根据用户输入的整数a的值执行不同的操作。
  3. 如果a的值为1,则输出"a的值为1"。
  4. 如果a的值为2,则输出"a的值为2"。
  5. 如果a的值为3,则输出"a的值为3"。
  6. 如果a的值不是1、2、3,则输出"a的值不是1、2、3"。
  7. 最后关闭Scanner对象,释放资源。
  • 2.程序输出结果:
  1. 如果用户输入的整数a的值为1,则输出"a的值为1"。
  2. 如果用户输入的整数a的值为2,则输出"a的值为2"。
  3. 如果用户输入的整数a的值为3,则输出"a的值为3"。
  4. 如果用户输入的整数a的值不是1、2、3,则输出"a的值不是1、2、3"。

1.switch语句执行的过程:

  1. 计算表达式的值,然后与每个case后面的常量进行比较。
  2. 如果表达式的值与某个case后面的常量相等,则执行该case后面的代码块。
  3. 如果表达式的值与所有case后面的常量都不相等,则执行default后面的代码块(如果有的话)。
  4. 如果某个case后面的代码块中包含了break语句,则执行完该代码块后,switch语句结束。

2.switch语句的特点:

  1. switch语句中的表达式可以是byte、short、int、char、String类型,case后面的常量值必须与表达式的类型相同。
  2. switch语句中的case后面的常量值必须是唯一的,不能重复。
  3. switch语句中的break语句用于终止switch语句的执行,如果不加break语句,程序会继续执行下一个case语句,直到遇到break语句或switch语句结束为止。4.
  4. switch语句中的case语句和default语句的顺序可以任意,但一般建议将default语句放在最后,以避免遗漏。
  5. default语句是可选的,用于处理所有case语句都不匹配的情况。
  6. switch语句中的case语句和default语句后面的代码块可以包含任意合法的Java语句,包括变量声明、赋值语句、控制语句等。
  7. switch语句实现的多分支结构,完全可以用if-else语句实现,但switch语句在某些情况下可以使代码更简洁、更易读。

switch语句典型应用:

import java.util.Scanner;

Scanner scan=new Scanner(System.in);
System.out.println("请输入分数=");
int score=scan.nextInt();

switch(score/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;
}

2.switch语句的嵌套

import java.util.Scanner;

Scanner scan=new Scanner(System.in);
System.out.print("请输入成绩=");
int score=scan.nextInt();
System.out.printf("%d\n成绩等级是:",score);

switch(score/10){
    case 10:
    case 9:
        System.out.println("优秀");
        switch(score){
            case 90:System.out.println("奖励一台手机");break;
            case 91:case 92:case 93:case 94:case 95:case 96:case 97:case 98:case 99:case 100: System.out.println("奖励一台电脑");break;
        }
        break;
    case 8:
        System.out.println("良好");
        break;
    case 7:
        System.out.println("中等");
        break;
    case 6:
        System.out.println("及格");
        break;
    default:
        System.out.println("不及格");
        break;
}

3.switch新特性

(1)Java12版本switch语句新特性

Switch 表达式在java12中引入了 -> 操作符,用于替代传统的冒号(:)。
与传统的 Switch 语句不同,使用 -> 的 case 分支不会出现 "fall-through" 现象,因此不需要 break 语句来防止穿透。这减少了代码的复杂性,也降低了编程错误的风险。

//利用java12的新我,上面的例子可以这样写
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 getTypeOfDay(String day) {
    String typeOfDay;
    switch (day) {
        case "MONDAY":
        case "TUESDAY":
        case "WEDNESDAY":
        case "THURSDAY":
        case "FRIDAY":
            typeOfDay = "Weekday";//工作日
            break;
        case "SATURDAY":
        case "SUNDAY":
            typeOfDay = "Weekend";//周末
            break;
        default:
            typeOfDay = "Unknown"; //未知
            break;        
    }
    return typeOfDay;
}
import java.util.Scanner;
import java.lang.String;
public  class MySwitch { 
//新版写法
    public static String getTypeOfDay(String day) {
    return switch (day) {
        case "MONDAY", "TUESDAY", "WEDNESDAY", "THURSDAY", "FRIDAY" -> "Weekday";
        case "SATURDAY", "SUNDAY" -> "Weekend";
        default -> "Unknown";
    }; 
    }
}
MySwitch.getTypeOfDay("MONDAY"); // "Weekday"
MySwitch.getTypeOfDay("FRIDAY"); // "Weekday"
MySwitch.getTypeOfDay("SATURDAY"); // "Weekend"

是不是简洁了很多。从这里可以看出他们之间的差异如下:

  • 返回1值:老的 Switch 仅仅只是语句,用来控制流程的,无法返回值。但是新的 Switch 可以作为表达式使用,支持返回值。
  • 1->** 代替**:老的 Switch 需要在每个案例后面使用 break ,否则会发生“穿透”,而新的不需要,它会自动终止。
  • 多值匹配:老的 Switch 无法在一个案例标签中匹配多个值,而新的 Switch 表达式允许一个 case 匹配多个值,用"," 分割即可。
  • 更简洁的语法: 整体代码更简洁,易于阅读和维护。

ava 12 引入 Switch 表达式,它解决了传统 Switch 语句的两个缺陷:

  • "Fall-through" 行为:在没有显式 break 语句的情况下,Switch 语句会从一个 case "穿透" 到下一个 case,忽略了这个会导致不可饶恕的错误。
  • 代码冗余:每个 case,我们都需要重复类似的代码结构,增加了代码的冗余和维护难度。
(2)Java13版本switch语句新特性

Java13对Switch表达式引入yield关键字来处理多分支结构中的返回值
Java12虽然解决这两个问题,但是还是有一个不好的地方,就是返回值,比如在处理复杂的逻辑时,仍需依赖外部变量来返回结果。所以Java13对Switch表达式进行了扩展,引入 yield关键字来处理多分支结构中的返回值,如下:

public static String getTypeOfDay(String day) {
    return switch (day) {
        case "MONDAY", "TUESDAY", "WEDNESDAY", "THURSDAY", "FRIDAY" ->  "Weekday";
        case "SATURDAY", "SUNDAY" ->  "Weekend";
        default -> {
            if (day.isEmpty()) {
               "day is empty"; //yield
            } else {
                 "Unknown"; //yield
            }
        }
    };
}
getTypeOfDay("MONDAY"); // "Weekday"
getTypeOfDay("SATURDAY"); // "Weekend"
getTypeOfDay(""); // "day is empty"

getTypeOfDay("FREDAY"); // "Unknown"
(3)Java17版本switch语句新特性

Java 17 模式匹配的应用扩展到了switch表达式
在Java 17中,switch表达式可以应用模式匹配,以提供更简洁和直观的语法。这使得switch表达式在处理复杂逻辑时更加灵活和强大。
switch 模式匹配支持以下几种模式:

  • 类型模式
  • 空模式
  • 守卫模式
  • 常量模式

类型模式
不知道同学们注意没有,Switch 表达式只有一种类型,如果我们要处理多种类型呢?我们只能这样处理

在线编辑器:https://gitcode.com/gh_mirrors/ij/IJava/?utm_source=artical_gitcode&index=bottom&type=card&webUrl&isLogin=1

//举个例子来说明下:

   
    public void switchTest() {
        Object[] objects = { "Hello", 123, "World", "Java", 3.14, "skjava" };
        for (Object obj: objects) {
            if (obj instanceof Integer intR) {
                System.out.println("为整数型:" + intR);
            } else if (obj instanceof Float floatR) {
                System.out.println("为浮点型:" + floatR);
            } else if (obj instanceof Double doubleR) {
            System.out.println("为双精度浮点数:" + doubleR);
            } else if (obj instanceof String str) {
                System.out.println("为字符串:" + str);
            } else {
                System.out.println("其他类型:" + obj);
            }
        }
    }
//我们用 Switch 表达式来改造下:

    @Test
    public void switchTest() {
        Object[] objects = { "Hello", 123, "World", "Java", 3.14, "skjava" };
        for (Object obj: objects) {
            switch (obj) {
                case Integer intR -> System.out.println("为整数型:" + intR);
                case Float floatR -> System.out.println("为浮点型:" + floatR);
                case Double doubleR -> System.out.println("为双精度浮点数:" + doubleR);
                case String str -> System.out.println("为字符串:" + str);
                default -> System.out.println("其他类型:" + obj);
            }
        }
    }

相比上面的 if...else 简洁了很多。同时在 Java 17 之前,Switch 选择器表达式只支持特定类型,即基本整型数据类型byte、short、char和int;对应的装箱形式Byte、Short、Character和Integer;String类;枚举类型。现在有了类型模式,Switch 表达式可以是任何类型啦。

空模式
在Java17之前,向switch语句传递一个null值,会抛出一个NullPointerException,现在可以通过类型模式,将 null 检查作为一个单独的case标签来处理,如下:

    public void switchTest() {
        Object[] objects = { "Hello", 123, "World", "Java", 3.14, "skjava" };
        for (Object obj: objects) {
            switch (obj) {
                // 省略...
                case null -> System.out.println("为空值");
                default -> System.out.println("其他类型:" + obj);
            }
        }
    }   
//case null 可以直接匹配值为 null 的情况。

守卫模式
守卫模式允许我们在 case 标签后添加一个额外的条件。只有当类型匹配并且额外条件为真时,才会进入该 case 块。

比如上面例子,我们要将字符串那块逻辑调整下,比如长度大于 5 的为长字符串,小于 5 的为短字符串,在不使用守卫模式的情况下,我们一般这样写:

public void switchTest() {
    Object[] objects = { "Hello", 123, "World", "Java", 3.14, "skjava" };
    for (Object obj: objects) {
        switch (obj) {
            case Integer intR -> System.out.println("为整数型:" + intR);
            case Float floatR -> System.out.println("为浮点型:" + floatR);
            case Double doubleR -> System.out.println("为双精度浮点数:" + doubleR);
            case String str -> {
                if (str.length() > 5) {
                    System.out.println("为长字符串:" + str);
                } else {
                    System.out.println("为短字符串:" + str);
                }
            }
            case null -> System.out.println("为空值");
            default -> System.out.println("其他类型:" + obj);
        }
    }
}

这种写法就显得不是那么友好,使用守卫模式如下:


    public void switchTest() {
        Object[] objects = { "Hello", 123, "World", "Java", 3.14, "skjava" };
        for (Object obj: objects) {
            switch (obj) {
                case Integer intR -> System.out.println("为整数型:" + intR);
                case Float floatR -> System.out.println("为浮点型:" + floatR);
                case Double doubleR -> System.out.println("为双精度浮点数:" + doubleR);
                case String str && str.length() > 5 -> System.out.println("为长字符串:" + str);
                case String str -> System.out.println("为短字符串:" + str);
                case null -> System.out.println("为空值");
                default -> System.out.println("其他类型:" + obj);
            }
        }
    }
//复制代码
//使用守卫模式,我们可以编写更灵活和表达性强的代码。
独学而无友,则孤陋而寡闻。
posted on 2024-09-28 19:18  安绍峰  阅读(138)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2026
浙公网安备 33010602011771号 浙ICP备2021040463号-3