程序员scholar 程序员scholar
首页
  • Java 基础

    • JavaSE
    • JavaIO
    • JavaAPI速查
  • Java 高级

    • JUC
    • JVM
    • Java新特性
    • 设计模式
  • Web 开发

    • Servlet
    • Java网络编程
  • Web 标准

    • HTML
    • CSS
    • JavaScript
  • 前端框架

    • Vue2
    • Vue3
    • Vue3 + TS
    • 微信小程序
    • uni-app
  • 工具与库

    • jQuery
    • Ajax
    • Axios
    • Webpack
    • Vuex
    • WebSocket
    • 第三方登录
  • 后端与语言扩展

    • ES6
    • Typescript
    • node.js
  • Element-UI
  • Apache ECharts
  • 数据结构
  • HTTP协议
  • HTTPS协议
  • 计算机网络
  • Linux常用命令
  • Windows常用命令
  • SQL数据库

    • MySQL
    • MySQL速查
  • NoSQL数据库

    • Redis
    • ElasticSearch
  • 数据库

    • MyBatis
    • MyBatis-Plus
  • 消息中间件

    • RabbitMQ
  • 服务器

    • Nginx
  • Spring框架

    • Spring6
    • SpringMVC
    • SpringBoot
    • SpringSecurity
  • SpringCould微服务

    • SpringCloud基础
    • 微服务之DDD架构思想
  • 日常必备

    • 开发常用工具包
    • Hutoll工具包
    • IDEA常用配置
    • 开发笔记
    • 日常记录
    • 项目部署
    • 网站导航
    • 产品学习
    • 英语学习
  • 代码管理

    • Maven
    • Git教程
    • Git小乌龟教程
  • 运维工具

    • Docker
    • Jenkins
    • Kubernetes
  • 算法笔记

    • 算法思想
    • 刷题笔记
  • 面试问题常见

    • 十大经典排序算法
    • 面试常见问题集锦
关于
GitHub (opens new window)
首页
  • Java 基础

    • JavaSE
    • JavaIO
    • JavaAPI速查
  • Java 高级

    • JUC
    • JVM
    • Java新特性
    • 设计模式
  • Web 开发

    • Servlet
    • Java网络编程
  • Web 标准

    • HTML
    • CSS
    • JavaScript
  • 前端框架

    • Vue2
    • Vue3
    • Vue3 + TS
    • 微信小程序
    • uni-app
  • 工具与库

    • jQuery
    • Ajax
    • Axios
    • Webpack
    • Vuex
    • WebSocket
    • 第三方登录
  • 后端与语言扩展

    • ES6
    • Typescript
    • node.js
  • Element-UI
  • Apache ECharts
  • 数据结构
  • HTTP协议
  • HTTPS协议
  • 计算机网络
  • Linux常用命令
  • Windows常用命令
  • SQL数据库

    • MySQL
    • MySQL速查
  • NoSQL数据库

    • Redis
    • ElasticSearch
  • 数据库

    • MyBatis
    • MyBatis-Plus
  • 消息中间件

    • RabbitMQ
  • 服务器

    • Nginx
  • Spring框架

    • Spring6
    • SpringMVC
    • SpringBoot
    • SpringSecurity
  • SpringCould微服务

    • SpringCloud基础
    • 微服务之DDD架构思想
  • 日常必备

    • 开发常用工具包
    • Hutoll工具包
    • IDEA常用配置
    • 开发笔记
    • 日常记录
    • 项目部署
    • 网站导航
    • 产品学习
    • 英语学习
  • 代码管理

    • Maven
    • Git教程
    • Git小乌龟教程
  • 运维工具

    • Docker
    • Jenkins
    • Kubernetes
  • 算法笔记

    • 算法思想
    • 刷题笔记
  • 面试问题常见

    • 十大经典排序算法
    • 面试常见问题集锦
关于
GitHub (opens new window)
npm

(进入注册为作者充电)

  • JavaSE - 基础篇

    • Java环境搭建
    • Java基础语法
    • Java数据类型
    • Java常量和变量
    • Java进制和存储
    • Java运算符
    • Java流程控制
      • 前言
      • 1. 流程控制概述
      • 2. Scanner类的使用
        • 2.1 Scanner类快速入门
        • 2.2 Scanner类中的hasNextXxx()方法
        • 1. hasNext()
        • 2. hasNextInt()
        • 3. hasNextDouble()
        • 4. hasNextLine()
      • 3. 分支结构
        • 3.1 分支语句1:if-else结构
        • if-else使用说明
        • if-else代码示例
        • 练习1:岳小鹏的成绩奖励
        • 练习2:三个整数的排序
        • 练习3:狗的年龄相当于人的年龄
        • 练习4:彩票游戏
        • 练习5:婚姻匹配
        • 3.2 分支语句2:switch-case结构
        • switch-case代码示例
        • 练习1:小写转大写
        • 练习2:成绩判断
        • 练习3:判断季节
        • 练习4:日期转换为年中的天数
        • 练习5:闰年判断
        • 练习6:生肖计算
      • 4. 循环结构
        • 4.1 for循环
        • for循环示例代码
        • 练习1:多重条件的循环打印
        • 练习2:最大公约数和最小公倍数
        • 练习3:水仙花数
        • 4.2 while循环
        • while循环示例代码
        • 4.3 do-while循环
        • do-while循环示例代码
        • 练习1:遍历100以内的所有偶数
        • 练习2:从键盘读入不定个数的整数
        • 4.4 嵌套循环结构
        • 练习1:九九乘法表及图形打印
        • 练习2:100以内的所有质数
        • 练习2的优化:100000以内的所有质数
        • 4.5 break、continue 和 return 的使用
        • 1. break的使用
        • 2. continue的使用
        • 3. return的使用
        • 4. 特殊流程控制语句说明
        • 5. 总结
    • Java数组
    • Java面向对象上
    • Java面向对象下
    • Java异常机制
    • Java枚举
    • Java反射机制
    • Java代理模式
    • Java泛型
    • Java序列化
    • Java多线程详解
    • Java线程池相关
  • Java
  • JavaSE - 基础篇
scholar
2024-03-17
目录

Java流程控制

# 前言

Java以前自学过一些,现在工作了,时间太久有一些知识都遗忘了,今天开始就更新Java了,想着把之前的Java基础知识捡起来;从最基础的开始,打好Java基础,便于以后复习。也欢迎大家跟我一起复习。

# 1. 流程控制概述

流程控制语句是用来控制程序中各语句执行顺序的语句,可以把语句组合成能完成一定功能的小逻辑模块。

其流程控制方式采用结构化程序设计中规定的三种基本流程结构,即:

  • 顺序结构
  • 分支结构
  • 循环结构

1. 顺序结构

这是最基本的流程控制,没有任何条件判断和跳转,程序按照代码的编写顺序,从上到下逐行执行。在顺序结构中,每一条指令都有一个明确的前后关系。


2. 分支结构

分支结构允许程序根据一个或多个条件选择性地执行某段代码。Java提供了两种主要的分支控制语句:

  • if…else语句:根据条件表达式的真假,选择执行两个代码块中的一个。此外,还可以通过多个if...else if...else结构来实现多重选择。
  • switch-case语句:根据一个表达式的值,选择性地执行多个代码块中的一个。switch-case结构适合于当变量等于不同值时执行不同的代码路径。

3. 循环结构

循环结构允许重复执行某段代码,直到满足特定的条件。Java中提供了三种基本的循环结构:

  • while循环:先判断条件,条件为真则执行循环体。循环体执行完毕后,再次判断条件,如此循环直到条件为假。
  • do-while循环:先执行一次循环体,然后判断条件,条件为真则继续执行循环体,如此循环直到条件为假。至少执行一次循环体。
  • for循环:在循环开始前初始化变量,然后判断条件,条件为真则执行循环体,执行完循环体后更新变量。循环直到条件为假。
  • foreach循环:JDK 1.5引入的循环结构,主要用于遍历数组或集合。语法简洁,自动处理迭代,减少了出错的可能性。

# 2. Scanner类的使用

之前我们学的基本语法中我们并没有实现程序和人的交互,但是Java给我们提供了这样一个工具类,我 们可以获取用户的输入。java.util.Scanner 是 Java5 的新特征,我们可以通过 Scanner 类来获取用户的输入。

# 2.1 Scanner类快速入门

  1. 导包:import java.util.Scanner;。
  2. 创建 Scanner 对象:Scanner scan = new Scanner(System.in);。
  3. next() / nextXxx(),来获取指定类型的变量,如nextInt() 获取一个 Int 型整数,nextDouble() 获取一个 Double 型浮点数。
  4. 释放资源:scan.close();。

Scanner类交互过程解释

  • 扫描(Scanning): Scanner类从输入缓冲区中取数据的过程。如果缓冲区中已经有了预期类型的数据,则Scanner将直接读取这些数据,无需用户重新输入。
  • 键入(Typing): 用户通过键盘输入数据的过程。数据的输入以换行符作为结束的标志,即用户按下Enter键后输入结束,Scanner随后从输入缓冲区中读取这些数据。

next() 和 nextLine() 的区别

  • next()和nextLine()都是读取字符串的方法。

  • next()和nextLine()的键入过程相同,扫描过程不同。

    • next()会忽略掉有效字符之前遇到的”空格“以及“换行符”,把有效字符后的“空格”或“换行符”作为扫描结束的标志,并且光标停在结束符之前。
    • nextLine()会读入“空格”,即将”空格“看为字符串的一部分,只把“换行符”作为扫描结束的标志,并且把光标移到“换行符”后。
    • nextInt()、nextDouble()等和next()扫描过程相同,只有nextLine()很特殊。

这样会出现的问题:先使用nextInt(),光标停在结束符之前,nextLine()可能会读到空字符串或者带空格的脏数据。

    Scanner scanner = new Scanner(System.in);
    String a = scanner.next();  //输入:123  qweqw
    String b = scanner.nextLine(); //先扫描缓冲区,发现还有"  qweqw",则没有键入过程。
    System.out.println(a); //读走"123",剩下"  qweqw"以及换行符
    System.out.println(b); //“换行符”是扫描结束的标志,则"  qweqw"
    scanner.close();
1
2
3
4
5
6
  • scanner.next(); 首先执行。它会读取输入直到遇到第一个空格,所以它只读取了123,并将其赋值给变量a。此时,缓冲区中剩下的内容是" qweqw\n"(注意:\n代表换行符,它是按下Enter键时产生的)。
  • 接下来,scanner.nextLine(); 执行。这个方法会读取当前位置直到行尾的内容,包括空格但不包含行的结束符(换行符)。因为next()方法执行后,光标停留在123和qweqw之间的空格上,所以nextLine()会从这个位置开始读取,直到行尾。结果是它读取了" qweqw"(包括前面的空格,但不包括结尾的换行符),并将其赋值给变量b。

解决办法

使用nextInt()后,先调用nextLine()把脏数据读走,将光标移到“换行符”后,再用nextLine()读取需要的数据,也就是使用 2 次nextLine()。

# 2.2 Scanner类中的hasNextXxx()方法

Scanner类还提供了一系列的hasNextXxx()方法,用于检查输入流中是否还有下一项符合Xxx类型的输入。其中,Xxx代表不同的类型,如Int、Double、Line等。这些方法都返回一个布尔值,如果输入流中的下一项可以转换为对应的类型,则返回true;否则返回false。这些方法非常有用,因为它们允许程序在尝试读取输入之前先检查输入是否符合预期的类型,从而避免输入不匹配的异常。

以下是一些hasNextXxx()方法的示例及其用法:

# 1. hasNext()

  • 检查是否还有下一项(不关心类型)。

  • 它会检查扫描器的输入缓冲区中是否还有数据。如果缓冲区中有数据,说明还有下一项输入。

Scanner scanner = new Scanner(System.in);
while (scanner.hasNext()) {
    String input = scanner.next();
    System.out.println(input);
}
1
2
3
4
5

源码解析:







 










 















// 这个方法用于检查扫描器的缓冲区内是否还有可读取的数据,不关心数据的具体类型
public boolean hasNext() {
    ensureOpen(); // 确保扫描器处于开启状态,如果已经关闭,则无法继续读取数据
    saveState(); // 保存当前扫描器的状态,以便在需要时可以恢复

    while (!sourceClosed) { // 循环直到数据源关闭为止
        if (hasTokenInBuffer()) // 如果缓冲区中存在可读取的数据(即token)
            return revertState(true); // 恢复扫描器之前的状态,并返回true表示有数据可读
        readInput(); // 如果缓冲区内没有数据,则尝试从数据源中读取更多数据到缓冲区
    }

    // 当数据源关闭后,再次检查缓冲区是否还有剩余的数据
    boolean result = hasTokenInBuffer(); 
    return revertState(result); // 根据最终检查结果恢复扫描器状态,并返回是否有数据可读
}

// 检查缓冲区内是否有可读取的数据(即token)
private boolean hasTokenInBuffer() {
    matchValid = false; // 初始化匹配状态为无效,表示当前还没有进行匹配操作
    matcher.usePattern(delimPattern); // 使用设置的分隔符模式来识别token
    matcher.region(position, buf.limit()); // 设置匹配区域,从当前读取位置到缓冲区末尾

    // 首先尝试跳过任何分隔符,因为我们只关心数据本身,而非分隔符
    if (matcher.lookingAt()) // 如果在当前读取位置找到了分隔符
        position = matcher.end(); // 将读取位置移动到分隔符之后,准备读取数据

    // 如果移动后的读取位置已经是缓冲区的末尾,说明缓冲区内不再有数据可读
    if (position == buf.limit()) 
        return false; // 返回false,表示缓冲区内没有数据

    return true; // 如果读取位置不是缓冲区末尾,说明缓冲区内还有数据,返回true
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32

总结

  • hasNext()方法的确是按照一种类似于next()方法的逻辑来检查缓冲区中是否还有数据的,首先会忽略掉有效字符之前遇到的”空格“以及“换行符”,然后从该位置检查数据是否存在, 把有效字符后的“空格”或“换行符”作为扫描结束的标志。
  • next()方法在找到token后会进一步提取和返回这个token,而hasNext()仅仅是检查是否存在这样的token,不会实际提取数据。

# 2. hasNextInt()

  • 检查是否还有符合整型的下一项输入。

  • 用法示例:在尝试读取一个整数之前检查输入是否为整数。

Scanner scanner = new Scanner(System.in);
while (scanner.hasNextInt()) {
    int number = scanner.nextInt();
    System.out.println("输入了整数:" + number);
}
1
2
3
4
5

源码解析:

public boolean hasNextInt(int radix) {
    // 设置数字的基数(如十进制、十六进制等)
    setRadix(radix);
    // 调用hasNext方法检查输入中是否存在下一个符合整数模式的数据
    // integerPattern()方法会返回一个正则表达式,这个表达式用于匹配整数
    boolean result = hasNext(integerPattern()); 
    if (result) { // 如果有匹配的整数
        try {
            // 从匹配结果中提取字符串
            String s = (matcher.group(SIMPLE_GROUP_INDEX) == null) ?
                processIntegerToken(hasNextResult) :
                hasNextResult;
            // 尝试将提取的字符串转换为整数并缓存结果
            typeCache = Integer.parseInt(s, radix);
        } catch (NumberFormatException nfe) {
            // 如果转换失败(比如字符串不是一个有效的整数),返回false
            result = false;
        }
    }
    return result;
}

// 按照整数模式进行匹配
public boolean hasNext(Pattern pattern) {
    ensureOpen(); // 确保扫描器已打开
    if (pattern == null) // 如果传入的模式为null,则抛出空指针异常
        throw new NullPointerException();
    hasNextPattern = null; // 清空之前的模式匹配结果
    saveState(); // 保存当前扫描器状态

    while (true) { // 循环直到找到匹配模式或者没有更多输入
        if (getCompleteTokenInBuffer(pattern) != null) { // 尝试在缓冲区中找到与模式匹配的完整token
            matchValid = true; // 如果找到了,设置匹配状态为有效
            cacheResult(); // 缓存匹配结果
            return revertState(true); // 恢复之前的扫描器状态,并返回true表示找到了匹配的模式
        }
        if (needInput) // 如果需要更多的输入来完成模式匹配
            readInput(); // 从数据源读取更多数据到缓冲区
        else
            return revertState(false); // 如果没有更多的输入,并且没有找到匹配的模式,则恢复之前的扫描器状态,并返回false
    }
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43

# 3. hasNextDouble()

  • 检查是否还有符合双精度浮点类型的下一项输入。

  • 用法示例:在尝试读取一个双精度浮点数之前检查输入是否为双精度浮点数。

Scanner scanner = new Scanner(System.in);
while (scanner.hasNextDouble()) {
    double number = scanner.nextDouble();
    System.out.println("输入了双精度浮点数:" + number);
}
1
2
3
4
5

# 4. hasNextLine()

  • 检查是否还有下一行输入。

  • 它会查看输入源(如文件或控制台输入)的缓冲区,判断是否存在下一行输入数据等待被读取

Scanner scanner = new Scanner(System.in);
while (scanner.hasNextLine()) {
    String line = scanner.nextLine();
    System.out.println(line);
}
1
2
3
4
5

源码解析:

public boolean hasNextLine() {
    // 首先,保存当前扫描器的状态。这一步很重要,因为如果下一行不存在,我们需要恢复到原始状态。
    saveState();

    // 使用findWithinHorizon方法尝试找到与行模式匹配的下一段文本。这里的0表示没有搜索范围的限制。
    String result = findWithinHorizon(linePattern(), 0);
    if (result != null) {
        // 如果找到了匹配的文本,接下来检查是否有行分隔符(如\n或\r\n)
        MatchResult mr = this.match();
        String lineSep = mr.group(1);
        if (lineSep != null) {
            // 如果存在行分隔符,去除它并只保留文本内容
            result = result.substring(0, result.length() - lineSep.length());
            cacheResult(result);
        } else {
            // 如果没有行分隔符,说明已经到达了文本的末尾或者是只有一行的情况
            cacheResult();
        }
    }
    // 恢复到之前保存的扫描器状态。这样做是为了不影响后续的扫描操作。
    revertState();

    // 返回是否找到了下一行。如果result不为null,说明成功找到了下一行文本,返回true;否则返回false。
    return (result != null);
}

// 这个方法是用来编译匹配行的正则表达式,用于识别换行符
private static Pattern linePattern() {
    // 使用单例模式来缓存编译后的Pattern对象,以避免重复编译带来的性能损耗
    Pattern lp = linePattern;
    if (lp == null) {
        linePattern = lp = Pattern.compile(LINE_PATTERN);
    }
    return lp;
}

// 这个方法负责在输入缓冲区中寻找与给定模式匹配的文本,考虑到了搜索范围(horizon)
public String findWithinHorizon(Pattern pattern, int horizon) {
    // 确保扫描器处于开启状态,否则抛出异常
    ensureOpen();
    if (pattern == null) throw new NullPointerException("模式对象不能为空");
    if (horizon < 0) throw new IllegalArgumentException("搜索范围不能为负");

    // 清空之前的匹配缓存,以便新的搜索
    clearCaches();

    // 循环在输入缓冲区中寻找与模式匹配的文本
    while (true) {
        String token = findPatternInBuffer(pattern, horizon);
        if (token != null) {
            // 如果找到了匹配的文本,标记当前匹配为有效,并返回这段文本
            matchValid = true;
            return token;
        }
        if (needInput) {
            // 如果需要更多输入才能继续当前匹配,尝试读入更多数据
            readInput();
        } else {
            // 如果已经读到输入的末尾,退出循环
            break;
        }
    }
    return null; // 如果没有找到匹配的文本,返回null
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64

总结

linePattern()方法定义了一个模式来识别换行符,这样Scanner就可以使用这个模式来查找输入中的换行符位置。然后,findWithinHorizon方法根据这个模式,在当前扫描器的缓冲区中搜索匹配的文本段。如果找到了与linePattern模式匹配的文本(即换行符),就表示存在下一行文本。这样,Scanner就能通过换行符的位置来确定何处开始读取下一行数据,从而实现逐行扫描输入文本的功能

# 3. 分支结构

# 3.1 分支语句1:if-else结构

在Java编程中,if-else是最基本的分支结构,用于根据条件表达式的真假来执行不同的代码块。下面详细解释if-else的使用说明和提供的练习示例。

# if-else使用说明

  1. 条件表达式:if或else if后面的条件表达式必须是布尔表达式(即结果为true或false的表达式),可以是关系表达式、逻辑表达式或布尔变量。

  2. 语句块简写:如果if或else代码块中只包含一条执行语句,可以省略大括号{}。但为了代码的清晰可读,建议始终保留大括号。

  3. 嵌套使用:if-else结构可以根据需要进行嵌套使用,以实现更复杂的逻辑判断。

  4. else可选:在“多选一”的if-else结构中,最后的else是可选的。如果所有条件都不满足时不需要执行任何操作,可以省略最后的else。

  5. 条件判断顺序:

    • 当多个条件是“互斥”关系(即条件之间没有交集)时,条件判断语句的顺序可以任意。
    • 当多个条件是“包含”关系(即较小范围的条件被较大范围的条件包含)时,建议将范围较小的条件放在前面判断(“小上大下/子上父下”原则)。

# if-else代码示例

class IfTest {
    public static void main(String[] args) {
        // 例1:心跳检测
        int heartBeats = 75;
        if (heartBeats < 60 || heartBeats > 100) {
            System.out.println("需要进一步做检查");
        }
        System.out.println("检查结束");

        // 例2:年龄判断
        int age = 23;
        if (age < 18) {
            System.out.println("你还可以看动画片");
        } else {
            System.out.println("你可以看科幻电影了");
        }

        // 例3:多重条件判断
        if (age < 0) {
            System.out.println("你输入的数据不合适");
        } else if (age < 18) {
            System.out.println("你还是个青少年");
        } else if (age < 35) {
            System.out.println("你还是个青壮年");
        } else if (age < 60) {
            System.out.println("你还是个中年");
        } else if (age < 120) {
            System.out.println("你进入老年了");
        } else {
            System.out.println("你成仙了");
        }
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33

通过这些示例,我们可以看到if-else结构的灵活性和实用性,能够根据不同的条件执行不同的逻辑分支,是程序中控制流程不可或缺的一部分。在实际编程中,合理地使用if-else结构可以使程序逻辑更加清晰、简洁。

# 练习1:岳小鹏的成绩奖励

/*
岳小鹏参加Java考试,他和父亲岳不群达成承诺:
如果:成绩为100分时,奖励一辆BMW;
成绩为(80,99]时,奖励一台iphone xs max;
当成绩为[60,80]时,奖励一个iPad;
其它时,什么奖励也没有。
请从键盘输入岳小鹏的期末成绩,并加以判断

说明:
1.else结构是可选的。
2.针对于条件表达式:
	① 如果多个条件表达式之间的关系是“互斥”关系(或没有交集的关系),哪个判断和执行语句声明在上面还是下面,无所谓;
	② 如果多个条件表达式之间是有交集的关系,需要根据实际情况,需要考虑实际情况,考虑清楚应该将哪个结构声明在上面。
	③ 如果多个条件表达式之间有包含的关系,通常情况下,需要将范围小的声明在范围大的上面。否则,范围小的就没机会运行。
*/
import java.util.Scanner;
class IFTest02{
	public static void main(String[] args){
		Scanner scan = new Scanner(System.in);
		System.out.println("请输入岳小鹏的成绩:");
		int score = scan.nextInt();

		if(score == 100){
			System.out.println("奖励一辆BMW");
		}else if(score >80 && score <=99){
			System.out.println("奖励一台iphone xs max");
		}else if(score >= 60 && score <= 80){
			System.out.println("奖励一个iPad");
		}else{
			System.out.println("奖励?学习去!!!");
		}
	}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33

# 练习2:三个整数的排序

/*
编写程序:由键盘输入三个整数分别存入变量num1、num2、num3,
对它们进行排序(使用if-else if-else),并且从小到大输出。

*/
import java.util.Scanner;

class Sorting{
	public static void main(String[] args){
		//Scanner实例化
		Scanner scan = new Scanner(System.in);
		System.out.println("请输入第一个整数:");
		int num1 = scan.nextInt();
		System.out.println("请输入第二个整数:");
		int num2 = scan.nextInt();
		System.out.println("请输入第三个整数:");
		int num3 = scan.nextInt();

		int MaxNumber = 0;
		if(num1 >= num2 ){
			if(num3 >= num1){
				System.out.println(num2 + "," + num1 + "," + num3);
			}else if(num3 <= num2){
				System.out.println(num3 + "," + num2 + "," + num1);
			}else{
				System.out.println(num2 + "," + num3 + "," + num1);
			}
		}else{
			if(num3 >= num2){
				System.out.println(num1 + "," + num2 + "," + num3);
			}else if(num3 <= num1){
				System.out.println(num3 + "," + num1 + "," + num2);
			}else{
				System.out.println(num1 + "," + num3 + "," + num2);
			}
		}
	}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38

# 练习3:狗的年龄相当于人的年龄

/*
我家的狗5岁了,5岁的狗相当于人类多大呢?
其实,狗的前两年每一年相当于人类的10.5岁,之后每增加一年就增加四岁。
那么5岁的狗相当于人类多少年龄呢?应该是:10.5 + 10.5 + 4 + 4 + 4 = 33岁。
如果用户输入负数,请显示一个提示信息。

*/
import java.util.Scanner;

class DogYear{
	public static void main(String[] args) {
		Scanner scan = new Scanner(System.in);
		System.out.println("请输入狗的年龄:");
		double Dyear = scan.nextDouble();
		if(Dyear <= 2 &&  Dyear > 0){
			System.out.println("狗的年龄等同于人的:" + Dyear * 10.5);
		}else if(Dyear <= 0){
			System.out.println("你输入的不正确。");
		}else{
			double number = 2 * 10.5 + (Dyear - 2) * 4;
			System.out.println("狗的年龄等同于人的:" + number);
		}		
	}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

# 练习4:彩票游戏

/*
假设你想开发一个玩彩票的游戏,程序随机地产生一个两位数的彩票,
提示用户输入一个两位数,然后按照下面的规则判定用户是否能赢。
1)如果用户输入的数匹配彩票的实际顺序,奖金10 000美元。
2)如果用户输入的所有数字匹配彩票的所有数字,但顺序不一致,奖金3 000美元。
3)如果用户输入的一个数字仅满足顺序情况下匹配彩票的一个数字,奖金1 000美元。
4)如果用户输入的一个数字仅满足非顺序情况下匹配彩票的一个数字,奖金500美元。
5)如果用户输入的数字没有匹配任何一个数字,则彩票作废。
提示:使用(int)(Math.random() * 90  + 10)产生随机数。
Math.random() : [0,1)  * 90 [0,90) + 10 [10,100)[10,99]

*/
import java.util.Scanner;

class CaiTest{
	public static void main(String[] args){
		//1、随机产生一个两位数
		//System.out.println(Math.random());//产生[0,1)
		int number = (int)(Math.random()*90 + 10);//得到[10,99],即[10,100)
		//System.out.println(number);
		
		int numberShi = number/10;
		int numberGe = number%10;
		
		//2、用户输入一个两位数
		Scanner input = new Scanner(System.in);
		System.out.print("请输入一个两位数:");
		int guess = input.nextInt();
		
		int guessShi = guess/10;
		int guessGe = guess%10;
		
		if(number == guess){
			System.out.println("奖金10 000美元");
		}else if(numberShi == guessGe && numberGe == guessShi){
			System.out.println("奖金3 000美元");
		}else if(numberShi==guessShi || numberGe == guessGe){
			System.out.println("奖金1 000美元");
		}else if(numberShi==guessGe || numberGe == guessShi){
			System.out.println("奖金500美元");
		}else{
			System.out.println("没中奖");
		}
		
		System.out.println("中奖号码是:" + number);
	}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47

# 练习5:婚姻匹配

/*
大家都知道,男大当婚,女大当嫁。
那么女方家长要嫁女儿,当然要提出一定的条件:高:180cm以上;
富:财富1千万以上;帅:是。如果这三个条件同时满足,则:“我一定要嫁给他!!!”
如果三个条件有为真的情况,则:“嫁吧,比上不足,比下有余。”
如果三个条件都不满足,则:“不嫁!”

*/
import java.util.Scanner;

class GaoFuTest{
	public static void main(String[] args){
		Scanner scan = new Scanner(System.in);

		System.out.println("请输入你的身高:(cm)");
		int height = scan.nextInt();
		System.out.println("请输入你的财富:(千万)");
		double weight = scan.nextDouble();
//		System.out.println("请输入你是否帅:(true/false)");
//		boolean isHandSome = scan.nextBoolean();

//		if(height >= 180 && weight >= 1 && isHandSome){
//			System.out.println("我一定要嫁给他!!!");
//		}else if(height >= 180 || weight >= 1 || isHandSome){
//			System.out.println("嫁吧,比上不足,比下有余。");
//		}else{
//			System.out.println("不嫁!");
//		}

		//方式二
		System.out.println("请输入你是否帅: (是or否)");
		String isHandsome = scan.next();

		if(height >= 100 && weight >= 1 && isHandsome.equals("是")){
			System.out.println("我一定要嫁给他!!!");
		}else if(height >= 180 || weight >= 1 || isHandsome.equals("是")){
			System.out.println("嫁吧,比上不足,比下有余。");
		}else{
			System.out.println("不嫁!");
		}
	}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42

# 3.2 分支语句2:switch-case结构

注意事项

switch结构中的表达式,只能是如下的六种数据类型之一:byte、short、char、int、枚举类型(JDK5.0)、String类型(JDK7.0)

不能是:long,float,double,boolean。

在Java中,switch-case语句是一种分支控制结构,它根据一个表达式的值来执行不同的代码段。下面详细解释switch-case的格式、说明和代码示例。

switch(表达式) {
    case 常量1:
        执行语句1;
        break;
    case 常量2:
        执行语句2;
        break;
    // 可以有任意数量的case语句
    default:
        执行语句n;
        break; // default中的break是可选的
}
1
2
3
4
5
6
7
8
9
10
11
12
  1. 表达式的值与case常量的匹配:switch语句根据表达式的值,依次与每个case后的常量值进行比较。如果匹配成功,则从匹配的case开始执行,直到遇到break或switch语句的末尾。

  2. break关键字:用于退出switch-case结构。如果没有break,程序将会继续执行下一个case中的语句,直到遇到break或switch的末尾。

  3. 支持的数据类型:switch表达式支持的数据类型有:byte、short、char、int、枚举类型(自JDK 5.0起)、String类型(自JDK 7.0起)。

  4. case常量:case后面必须跟一个常量表达式,不能是范围。

  5. default分支:类似于if-else结构中的else,用于处理所有未被case匹配的情况。default分支是可选的,且其位置是灵活的,可以放在switch语句中的任何位置。

# switch-case代码示例

// 使用switch-case处理整数
int number = 2;
switch(number) {
    case 0:
        System.out.println("zero");
        break;
    case 1:
        System.out.println("one");
        break;
    case 2:
        System.out.println("two");
        break;
    case 3:
        System.out.println("three");
        break;
    default:
        System.out.println("other");
        break;
}

// 使用switch-case处理字符串
String season = "summer";
switch(season) {
    case "spring":
        System.out.println("春暖花开");
        break;
    case "summer":
        System.out.println("夏日炎炎");
        break;
    case "autumn":
        System.out.println("秋高气爽");
        break;
    case "winter":
        System.out.println("冬雪皑皑");
        break;
    default:
        System.out.println("季节输入有误");
        break;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39

注意:虽然switch-case可以处理字符串和枚举类型,但这些特性是在较新的Java版本中添加的。早期版本的Java中switch表达式只支持byte、short、char和int类型。在使用switch-case时,应当注意case后面跟的必须是常量表达式,且switch表达式的类型必须与case常量兼容。

# 练习1:小写转大写

/*
使用switch 把小写类型的char型转为大写。只转换a, b, c, d, e. 其它的输出“other”。
提示:String word = scan.next();  char c = word.charAt(0); switch(c){}
*/
import java.util.Scanner;
class  SwitchCaseTest1{
	public static void main(String[] args) {
		Scanner scan = new Scanner(System.in);
		String word = scan.next();  
		char c = word.charAt(0); 
		switch(c){
		case 'a':
			System.out.println("A");
			break;
		case 'b':
			System.out.println("B");
			break;
		case 'c':
			System.out.println("C");
			break;
		case 'd':
			System.out.println("D");
			break;
		case 'e':
			System.out.println("E");
			break;
		default:
			System.out.println("other");
		}
	}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

# 练习2:成绩判断

/*
对学生成绩大于60分的,输出“合格”。低于60分的,输出“不合格”。

说明:如果switch-case语句中多个相同语句,可以进行合并。
*/
class  SwitchTest1{
	public static void main(String[] args){
		int score = 78;
		//方案一
		switch(score / 10){
		case 0:
		case 1:
		case 2:
		case 3:
		case 4:
		case 5:
			System.out.println("不合格");
			break;
		case 6:
		case 7:
		case 8:
		case 9:
		case 10:
			System.out.println("合格");
			break;
		}

		//更优的解法
		switch(score /60){
		case 0:
			System.out.println("不及格");
			break;
		case 1:
			System.out.println("合格");
			break;
		}
	}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38

# 练习3:判断季节

/*
根据用于指定月份,打印该月份所属的季节。
3,4,5 春季6,7,8 夏季9,10,11 秋季12, 1, 2 冬季

*/
class MonthTest{
	public static void main(String[] args){
		int month = 6;
		switch(month){
		case 12:
		case 1:
		case 2:
			System.out.println("冬季");
			break;
		case 3:
		case 4:
		case 5:
			System.out.println("春季");
			break;
		case 6:
		case 7:
		case 8:
			System.out.println("夏季");
			break;
		case 9:
		case 10:
		case 11:
			System.out.println("秋季");
			break;
		}
	}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32

# 练习4:日期转换为年中的天数

/*
编写程序:从键盘上输入2020年的“month”和“day”,
要求通过程序输出输入的日期为2019年的第几天。
2 15 : 31 + 15

5 7: 31 + 28 +31 +30 + 7
...
说明:break在switch-case中是可选的。
*/
import java.util.Scanner;
class DayTest{
	public static void main(String[] args) {
		Scanner scan = new Scanner(System.in);
		System.out.println("请输入2020年的month");
		int month = scan.nextInt();
		System.out.println("请输入2020年的day");
		int day = scan.nextInt();

		//定义一个变量来保存天数
		int sumDays = 0;
		switch(month){
		case 12:
			sumDays += 30;
		case 11:
			sumDays += 31;
		case 10:
			sumDays += 30;
		case 9:
			sumDays += 31;
		case 8:
			sumDays += 31;
		case 7:
			sumDays += 30;
		case 6:
			sumDays += 31;
		case 5:
			sumDays += 30;
		case 4:
			sumDays += 31;
		case 3:
			sumDays += 29;
		case 2:
			sumDays += 31;
		case 1:
			sumDays += day;
		}

		System.out.println("2020年" + month + "月" + day + "日是当年的第" + sumDays + "天");
	}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50

# 练习5:闰年判断

/*
从键盘分别输入年、月、日,判断这一天是当年的第几天注:判断一年是否是闰年的标准:
1)可以被4整除,但不可被100整除或
2)可以被400整除
(year % 4 == 0 && year % 100 != 0) || year %400 == 0)

说明:
1凡是可以使用switch-case的结构,都可以转换为if-else。反之,不成立。
2.我们写分支结构时,当发现既可以使用switch-case,〔(同时,switch中表达式的取值情况不太多),
又可以使用,我们优先选择使用switch-case。原因:switch-case执行效率稍高。

*/
import java.util.Scanner;
class YearDayTest{
	public static void main(String[] args) {
		Scanner scan = new Scanner(System.in);
		System.out.println("请输入year");
		int year = scan.nextInt();
		System.out.println("请输入month");
		int month = scan.nextInt();
		System.out.println("请输入day");
		int day = scan.nextInt();

		//定义一个变量来保存天数
		int sumDays = 0;
		switch(month){
		case 12:
			sumDays += 30;
		case 11:
			sumDays += 31;
		case 10:
			sumDays += 30;
		case 9:
			sumDays += 31;
		case 8:
			sumDays += 31;
		case 7:
			sumDays += 30;
		case 6:
			sumDays += 31;
		case 5:
			sumDays += 30;
		case 4:
			sumDays += 31;
		case 3:
			//判断是否为闰年
			if((year % 4 == 0 && year % 100 != 0) || year %400 == 0){
				sumDays += 29;
			}else{
				sumDays += 28;
			}
		case 2:
			sumDays += 31;
		case 1:
			sumDays += day;
		}

		System.out.println(year + "年" + month + "月" + day + "日是当年的第" + sumDays + "天");
	}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60

# 练习6:生肖计算

/*
编写一个程序,为一个给定的年份找出其对应的中国生肖。
中国的生肖基于12年一个周期,每年用一个动物代表:
rat、ox、tiger、rabbit、dragon、snake、horse、sheep、monkey、rooster、dog、pig。
提示:2019年:猪2019 % 12 == 3
*/
import java.util.Scanner;
class ZodiacSignTest{
	public static void main(String[] args){
		Scanner scan = new Scanner(System.in);
		System.out.println("请输入年份:");
		int year = scan.nextInt();
		switch (year % 12){
		case 1:
			System.out.println("rooster");
			break;
		case 2:
			System.out.println("dog");
			break;
		case 3:
			System.out.println("pig");
			break;
		case 4:
			System.out.println("rat");
			break;
		case 5:
			System.out.println("ox");
			break;
		case 6:
			System.out.println("tiger");
			break;
		case 7:
			System.out.println("rabbit");
			break;
		case 8:
			System.out.println("dragon");
			break;
		case 9:
			System.out.println("snake");
			break;
		case 10:
			System.out.println("horse");
			break;
		case 11:
			System.out.println("sheep");
			break;
		case 12:
			System.out.println("monkey");
			break;
		}
	}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52

# 4. 循环结构

1、循环结构

在某些条件满足的情况下,反复执行特定代码的功能

2、循环语句分类

  • for 循环
  • while 循环
  • do-while 循环

# 4.1 for循环

在Java中,for循环是一种基本的循环结构,用于重复执行一段代码直到满足指定条件为止。它是实现循环的一种非常灵活的方式,广泛用于遍历数组、集合或执行需要重复操作的任务。以下是对for循环的详细解释和示例。

for循环的语法格式

for (初始化部分; 循环条件部分; 迭代部分) {
    循环体部分;
}
1
2
3

执行过程

  1. 初始化部分:执行一次,在循环开始前设置循环控制变量的初始值。
  2. 循环条件部分:在每次循环开始前评估。如果条件为true,则执行循环体;如果条件为false,则退出循环。
  3. 循环体部分:包含需要重复执行的代码。
  4. 迭代部分:在每次循环体执行后执行,通常用于更新循环控制变量。

执行顺序:初始化 → 循环条件 → 循环体 → 迭代 → 循环条件 → ...

说明

  • 循环条件为boolean类型表达式,false时退出循环。
  • 初始化部分可以声明多个变量,但必须是相同的类型,用逗号分隔。
  • 迭代部分也可以有多个表达式,用逗号分隔。

# for循环示例代码

class ForTest {
    public static void main(String[] args) {
        // 打印"Hello World!"五次
        for (int i = 1; i <= 5; i++) {
            System.out.println("Hello World!");
        }

        // 特殊应用:在循环的初始化和迭代部分执行语句
        int num = 1;
        for (System.out.print('a'); num <= 3; System.out.print('c'), num++) {
            System.out.print('b');
        }
        // 输出:abcbcbc

        // 遍历100以内的偶数,计算所有偶数的和,并输出偶数的个数
        int sum = 0;    // 记录所有偶数的和
        int count = 0;  // 记录偶数的个数
        for (int i = 1; i <= 100; i++) {
            if (i % 2 == 0) {
                System.out.println(i);
                sum += i;
                count++;
            }
        }
        System.out.println("100以内的偶数的和:" + sum);
        System.out.println("个数为:" + count);
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

通过这些示例,我们可以看到for循环在实现计数循环和条件循环中的强大能力。它提供了一种结构化和易于理解的方式来重复执行代码块,使得代码更加简洁和易于维护。

# 练习1:多重条件的循环打印

/*
编写程序从1循环到150,并在每行打印一个值,
另外在每个3的倍数行上打印出“foo”,
在每个5的倍数行上打印“biz”,
在每个7的倍数行上打印输出“baz”。

*/
class ForTest1{
	public static void main(String[] args){
		
		for(int i = 1;i <= 150;i++ ){
			System.out.print(i + " ");
			if(i % 3 == 0){
				System.out.print("foo ");
			}
			if(i % 5 == 0){
				System.out.print("biz ");
			}
			if(i % 7 == 0){
				System.out.print("baz ");
			}

			//换行
			System.out.println();
		}
	}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

# 练习2:最大公约数和最小公倍数

/*
输入两个正整数m和n,求其最大公约数和最小公倍数。
比如:12和20的最大公约数是4,最小公倍数是60。说明:break关键字的使用

*/
import java.util.Scanner;
class GnumberTest{
	public static void main(String[] args){
		Scanner scan = new Scanner(System.in);
		System.out.println("请输入m:");
		int m = scan.nextInt();
		System.out.println("请输入n:");
		int n = scan.nextInt();
		//获取m和n的较大值
		int max = (m > n) ? m : n;
		//获取m和n的最小值
		int min = (m < n) ? m : n;
		
		//求最大公约数
		for(int i = min;i >= 1;i--){
			if(m % i == 0 && n % i == 0){
				System.out.println("m和n的最大公约数:" + i);
				break;
			}
		}

		//求最小公倍数
		for(int i = max;i <= m * n;i++){
			if( i % m == 0 && i % n == 0){
				System.out.println("m和n的最小公倍数是:" + i);
				break;
			}
		}
	}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35

# 练习3:水仙花数

/*
输出所有的水仙花数,所谓水仙花数是指一个3位数,其各个位上数字立方和等于其本身。
例如:153 = 1*1*1 + 3*3*3 + 5*5*5

*/
class ForTest2{
	public static void main(String[] args){
		for(int i = 100;i <= 999;i++){
			int a = i / 100;	//获取百位
			int b = i % 100 /10;	//获取十位
			int c = i % 10;	//获取个位
			if(a*a*a + b*b*b + c*c*c == i){
				System.out.println("此数值为满足条件的水仙花数:" + i);
			}
		}
	}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

# 4.2 while循环

while循环是Java中的一种基本循环结构,它用于重复执行一组操作直到指定的条件表达式结果为false。while循环非常适合用于不确定循环次数的情况,只需满足循环条件即可继续执行。

语法格式

初始化部分;
while(循环条件部分) {
    循环体部分;
    迭代部分;
}
1
2
3
4
5

执行过程

  1. 初始化部分:在循环开始之前设置循环控制变量的初始值。这一部分不是while循环语句的一部分,通常出现在while循环之前。

  2. 循环条件部分:是一个布尔表达式,每次循环开始前都会计算这个表达式的值。如果表达式的值为true,则执行循环体;如果为false,则结束循环。

  3. 循环体部分:包含了需要重复执行的代码块。

  4. 迭代部分:用于更新循环控制变量的值,以避免造成死循环。这部分代码位于循环体的末尾。

说明

  • 迭代部分的重要性:必须确保在循环体中有改变循环条件的语句,否则可能导致无限循环。

  • 与for循环的关系:while循环和for循环在功能上是等价的,任何for循环都可以改写成while循环,反之亦然。选择使用哪一种循环结构主要取决于哪种更能清晰地表达程序的意图。

# while循环示例代码

public class WhileLoopExample {
    public static void main(String[] args) {
        // 计算1到100的和
        int sum = 0;
        int i = 1; // 初始化部分
        while (i <= 100) { // 循环条件部分
            sum += i; // 循环体部分
            i++; // 迭代部分
        }
        System.out.println("1到100的和为:" + sum);
    }
}
1
2
3
4
5
6
7
8
9
10
11
12

在这个示例中,使用while循环计算从1到100的整数和。循环开始前初始化控制变量i为1,然后在循环条件部分检查i是否小于或等于100。在循环体中,将i的值累加到sum变量上,并在每次循环结束时通过i++更新i的值。当i超过100时,循环条件变为false,while循环结束。

# 4.3 do-while循环

do-while循环是Java中的另一种基本循环结构,它保证循环体至少被执行一次,即先执行循环体,然后判断循环条件是否满足,以决定是否继续执行循环。这与while循环的主要区别在于do-while循环至少执行一次循环体,无论循环条件初次判断的结果如何。

语法格式

初始化部分;
do {
    循环体部分;
    迭代部分;
} while (循环条件部分);
1
2
3
4
5

执行过程

  1. 初始化部分:在循环开始之前,设置循环控制变量的初始值。这一部分在do-while循环之前执行。

  2. 循环体部分:包含了需要重复执行的代码块,do-while循环确保循环体至少被执行一次。

  3. 迭代部分:通常用于更新循环控制变量的值,这部分位于循环体内部,确保在每次执行完循环体后进行。

  4. 循环条件部分:在循环体和迭代部分执行完毕后评估,如果条件为true,则继续执行循环体;如果为false,则结束循环。这个条件是一个布尔表达式。

说明

  • do-while循环至少执行一次循环体,这对于那些至少需要执行一次操作,然后根据某些条件决定是否继续执行的情况特别有用。

  • 类似于while循环,do-while循环中也需要确保有改变循环条件的语句,以避免无限循环。

# do-while循环示例代码

public class DoWhileLoopExample {
    public static void main(String[] args) {
        // 从1打印到5
        int i = 1; // 初始化部分
        do {
            System.out.println(i); // 循环体部分
            i++; // 迭代部分
        } while (i <= 5); // 循环条件部分
    }
}
1
2
3
4
5
6
7
8
9
10

在这个示例中,即使循环条件一开始就不满足(如果你将i初始化为更大的值,如6),循环体中的代码仍然会被执行一次。这说明了do-while循环至少执行一次循环体的特性。

do-while循环适用于循环体至少需要执行一次的场景,例如,至少显示一次菜单,并根据用户的选择决定是否继续显示。

# 练习1:遍历100以内的所有偶数

class DoWhileTest{
	public static void main(String[] args){
		//遍历100以内的所有偶数,并计算所有偶数的和和偶数的个数
		int number = 1;
		int sum = 0;	//记录总和
		int count = 0;	//记录个数
		do{
			if(number % 2 == 0){
				System.out.println(number);
				sum += number;
				count++;
			}
			number++;
		}while(number <= 100);

		System.out.println("总和为:" + sum);
		System.out.println("个数为:" + count);

		//*********************************
		int numb = 10;
		while(numb > 10){
			System.out.println("hello:while");
			numb--;
		}

		int numb2 = 10;
		do{
			System.out.println("hello:do-while");
			numb2--;
		}while(numb2 > 10);
	}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32

# 练习2:从键盘读入不定个数的整数

/*
从键盘读入个数不确定的整数,并判断读入的正数和负数的个数,输入为0时结束程序。

说明:
1.不在循环条件部分限制次数的结构:while(true) , for(true)
2.结束循环的几种方式:
	方式一:循环条件部分返回false;
	方式二:在循环体中,执行break;
*/
import java.util.Scanner;
class XunTest{
	public static void main(String[] args) {
		Scanner scan = new Scanner(System.in);
		int Positive = 0;	//正数个数
		int Negative = 0;	//负数个数
		while(true){
			int number = scan.nextInt();
			if(number > 0){
				Positive++;
			}else if(number < 0){
				Negative++;
			}else{
				//一旦执行,跳出循环。
				break;
			}	
		}

		System.out.println("正数的个数:" + Positive);
		System.out.println("负数的个数:" + Negative);
	}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

# 4.4 嵌套循环结构

  1. 嵌套循环定义:当一个循环结构(内层循环)被声明在另一个循环结构(外层循环)的循环体中,形成了嵌套循环。嵌套循环可以是任意类型的循环(for, while, do-while)相互嵌套。
  2. 外层循环控制行数:在处理多行数据或多行图形时,外层循环通常用于控制行数。每一次外层循环的迭代代表一行。
  3. 内层循环控制列数:内层循环通常用于控制每一行中的列数或元素数。在每次外层循环迭代中,内层循环可能会执行多次,每次执行代表一列。
  4. 执行次数:如果外层循环执行M次,内层循环每次执行N次,那么内层循环的循环体总共执行M * N次。

# 练习1:九九乘法表及图形打印

class ForForTest {
    public static void main(String[] args) {
        
        // 打印一行星号
        // 结果: ******
        for(int i = 1; i <= 6; i++) {
            System.out.print("*");
        }
        System.out.println(); // 换行

        System.out.println(); // 为不同的图形间增加空行,便于区分

        // 打印四行六列的星号
        // 结果:
        // ******
        // ******
        // ******
        // ******
        for(int i = 1; i <= 4; i++) {  
            for(int j = 1; j <= 6; j++) {  
                System.out.print('*');
            }
            System.out.println(); // 换行
        }

        System.out.println(); // 为不同的图形间增加空行,便于区分

        // 打印直角三角形
        // 结果:
        // *
        // **
        // ***
        // ****
        // *****
        for(int i = 1; i <= 5; i++) { // 控制行数
            for(int j = 1; j <= i; j++) { // 控制列数,每行星号的数量等于行号
                System.out.print("*");
            }
            System.out.println();
        }

        System.out.println(); // 为不同的图形间增加空行,便于区分

        // 打印倒直角三角形
        // 结果:
        // *****
        // ****
        // ***
        // **
        // *
        for(int i = 1; i <= 5; i++) {
            for(int j = 1; j <= 5 - i; j++) {
                System.out.print("*");
            }
            System.out.println();
        }

        System.out.println(); // 为不同的图形间增加空行,便于区分

        // 打印菱形的上半部分
        // 结果:
        // *
        // **
        // ***
        // ****
        // *****
        for(int i = 1; i <= 5; i++) {
            for(int j = 1; j <= i; j++) {
                System.out.print("*");
            }
            System.out.println();
        }

        // 打印菱形的下半部分
        // 结果(继续上半部分后):
        // ****
        // ***
        // **
        // *
        for(int i = 1; i <= 4; i++) {
            for(int j = 1; j <= 4 - i + 1; j++) {
                System.out.print("*");
            }
            System.out.println();
        }

        System.out.println(); // 为不同的图形间增加空行,便于区分

        // 九九乘法表
        // 结果:
        // 1*1=1 
        // 2*1=2 2*2=4 
        // ...
        // 9*1=9 9*2=18 ... 9*9=81
        for(int i = 1; i <= 9; i++) {
            for(int j = 1; j <= i; j++) {
                System.out.print(i + "*" + j + "=" + (i * j) + " ");
            }
            System.out.println(); // 换行
        }
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102

# 练习2:100以内的所有质数

/*
100以内的所有质数
质数:素数,只能被1和它本身整除的自然数。

最小的质数是:2
*/
class PrimeNuberTest{
	public static void main(String[] args){
		boolean isFlag = true;	//标识是否被除尽,一旦除尽,修改其值。

		for(int i = 2;i <= 100;i++){	//遍历100以内的自然数
			for(int j =2;j < i;j++){	//j:被i去除
				if(i % j == 0){	//i被j除尽
					isFlag = false;
				}
			}
			if(isFlag == true){
				System.out.println(i);
			}

			//重置isFlag
			isFlag = true;
		}
	}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

# 练习2的优化:100000以内的所有质数

/*
100000以内的所有质数
质数:素数,只能被1和它本身整除的自然数。

最小的质数是:2
*/

class PrimeNuberTest{
	public static void main(String[] args){
		boolean isFlag = true;	//标识是否被除尽,一旦除尽,修改其值。
		int count = 0;	//记录质数的个数

		//获取当前时间举例1970-01-01 00:00:00 的毫秒数
		long start = System.currentTimeMillis();

		for(int i = 2;i <= 100000;i++){	//遍历100以内的自然数
			//优化2:对本身是质数的自然数有效 5447---> 11
		//	for(int j =2;j < i;j++){	//j:被i去除
			for(int j =2;j <= Math.sqrt(i);j++){	//j:被i去除
				if(i % j == 0){	//i被j除尽
					isFlag = false;
					break;	//优化一:只对本身非质数的自然数是有效的。
				}
			}
			if(isFlag == true){
			//	System.out.println(i);
				count++;
			}

			//重置isFlag
			isFlag = true;
		}

		//获取当前时间举例1970-01-01 00:00:00 的毫秒数
		long end = System.currentTimeMillis();


		System.out.println("质数的个数:" + count);
		System.out.println("所花费的时间为:" + (end - start));	//16843 --> 5447	优化一
	}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41

# 4.5 break、continue 和 return 的使用

在Java中,break、continue和return都是控制流程的关键字,它们用于在不同情境下改变代码的执行流程。

# 1. break的使用

  • 基本用法:break语句用于立即退出循环,终止循环的继续执行。它只会影响包含它的最内层循环或switch语句。

    for(int i = 0; i < 10; i++) {
        if(i == 5) {
            break; // 当i等于5时退出循环
        }
        System.out.println(i);
    }
    
    1
    2
    3
    4
    5
    6
  • 标签用法:在嵌套循环中,break可以结合标签使用,直接跳出指定的外层循环。

    outer: for(int i = 0; i < 5; i++) {
        inner: for(int j = 0; j < 5; j++) {
            if(j == 2) {
                break outer; // 跳出outer标签所标识的循环
            }
            System.out.println("i=" + i + ", j=" + j);
        }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8

# 2. continue的使用

  • 基本用法:continue语句用于跳过当前循环的剩余部分,直接进入下一次循环的迭代。它只作用于最近的循环。

    for(int i = 0; i < 10; i++) {
        if(i % 2 == 0) {
            continue; // 跳过偶数的打印
        }
        System.out.println(i);
    }
    
    1
    2
    3
    4
    5
    6
  • 标签用法:continue也可以与标签一起使用,在嵌套循环中直接开始外层循环的下一次迭代。

    outer: for(int i = 0; i < 5; i++) {
        for(int j = 0; j < 5; j++) {
            if(j == 2) {
                continue outer; // 开始outer循环的下一次迭代
            }
            System.out.println("i=" + i + ", j=" + j);
        }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8

# 3. return的使用

  • 功能:return语句用于从当前方法中退出,并返回方法调用处,可选地返回一个值(对于非void方法)。return不仅能结束循环,还能结束包含它的方法的执行。

    public int testReturn() {
        for(int i = 0; i < 10; i++) {
            if(i == 5) {
                return i; // 返回当前的i值,并结束方法的执行
            }
        }
        return -1; // 如果循环正常结束,则返回-1
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
  • 与break和continue的区别:return直接结束整个方法,而break和continue只影响循环的流程。在嵌套循环中,使用return将会结束包含循环的整个方法,不仅仅是退出循环。

理解这三个关键字及其使用场景对于控制程序执行流程至关重要。在实际开发中,合理使用它们可以使代码逻辑更加清晰和灵活。

# 4. 特殊流程控制语句说明

  • break:用于立即退出最近的switch或循环语句(for、while、do-while),终止其后续操作。在switch中,break用来终止一个案例的执行。在循环中,它用来完全结束循环,不再继续迭代。
  • continue:仅用于循环语句中,用于立即结束当前迭代,跳过循环体中剩余的代码,直接开始下一次的迭代。它只影响当前所在的循环。
  • 共同点:两者都不能在循环或switch语句之外使用。使用后,它们之后的语句将不会执行,因此不能在它们之后添加任何代码。
  • 标号(Label)语句:用于与break和continue结合使用,指定要跳出或继续的特定循环层次。标号需放在循环之前。
  • 与goto的区别:虽然许多编程语言提供goto语句以允许随意跳转到程序的任意点,Java中没有goto语句,因为它会使程序逻辑变得复杂且难以理解。Java中的break和continue提供了更受控制的流程跳转方式。

# 5. 总结

以上便是本文的全部内容,本人才疏学浅,文章有什么错误的地方,欢迎大佬们批评指正!我是scholar,一个在互联网行业的小白,立志成为更好的自己。

如果你想了解更多关于scholar (opens new window) (opens new window),可以关注公众号-书生带你学编程,后面文章会首先同步至公众号。

公众号封面

编辑此页 (opens new window)
上次更新: 2024/12/28, 18:32:08
Java运算符
Java数组

← Java运算符 Java数组→

Theme by Vdoing | Copyright © 2019-2025 程序员scholar
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式