JAVA学习 DAY7 程序逻辑控制【万字长文!一篇搞定!】

  本系列可作为JAVA学习系列的笔记,文中提到的一些练习的代码,小编会将代码复制下来,大家复制下来就可以练习了,方便大家学习。

点赞关注不迷路!您的点赞、关注和收藏是对小编最大的支持和鼓励! 

本文篇幅较长,建议先收藏再食用!


 系列文章目录

JAVA学习 DAY1 初识JAVA

JAVA学习 DAY2 java程序运行、注意事项、转义字符

JAVA学习 DAY3 注释与编码规范讲解

JAVA学习 DAY4 DOS操作讲解及实例

JAVA学习 DAY5 变量&数据类型 [万字长文!一篇搞定!] 

JAVA学习 DAY6 运算符

JAVA学习 DAY7 程序逻辑控制【万字长文!一篇搞定!】

JAVA学习 DAY8 方法【万字长文!一篇搞定!】

JAVA学习 DAY9 数组【万字长文!一篇搞定!】

JAVA学习 DAY10 类和对象【万字长文!一篇搞定!】

JAVA学习 DAY11 类和对象_续1【万字长文!一篇搞定!】

JAVA学习 DAY12 继承和多态【万字长文!一篇搞定!】

JAVA学习 DAY13 抽象类和接口【万字长文!一篇搞定!】

深度剖析 Java 图书管理系统设计与实现:类、接口与对象的实战应用

JAVA学习 DAY15 Java String类

JAVA学习 DAY16 Java 异常

Java 基础全攻略:从语法到实战项目(简单总结)


 拓展文章

Sublime安装指导!只需四步!

图文详解汉诺塔问题:从递归思想到代码实现(零基础也能看懂)

Java避坑指南:千万别在构造方法中调用重写的方法!(附代码案例+执行流程全解析)

Java 接口学习核心难点深度解析

深入剖析 Java 中的深拷贝与浅拷贝:原理、实现与最佳实践

目录

 系列文章目录

前言

一、程序逻辑控制概述

1.1 程序执行流程的本质

1.2 逻辑控制的重要性

1.3 学习目标与核心内容

1.3.1 核心学习目标

1.3.2 笔记核心框架

二、顺序结构

2.1 顺序结构的定义与特点

2.2 语法格式与代码示例

2.2.1 基本语法格式

2.2.2 基础示例:顺序输出字符串

2.2.3 示例说明

2.2.4 扩展示例:变量运算的顺序执行

2.3 顺序结构的调整与影响

2.3.1 调整顺序后的示例

2.3.2 错误顺序示例(编译报错)

2.4 顺序结构的应用场景

2.5 顺序结构的注意事项

三、分支结构

3.1 if-else 语句

3.1.1 语法格式 1:单分支 if 语句

语法结构

语法说明

代码示例:成绩奖励判断

变体示例(布尔表达式为 false)

3.1.2 语法格式 2:双分支 if-else 语句

语法结构

语法说明

代码示例:成绩奖惩判断

练习 1:判断奇数偶数

练习 2:判断正数、负数或零

3.1.3 语法格式 3:多重分支 if-else if-else 语句

语法结构

语法说明

代码示例:成绩等级判断

练习 3:判断闰年

3.1.4 if 语句的嵌套

语法结构

语法说明

代码示例:嵌套判断学生成绩与性别

3.1.5 if 语句的注意事项

(1)代码风格规范

(2)分号问题(常见错误)

(3)悬垂 else 问题

(4)布尔表达式的简化

(5)变量作用域问题

3.2 switch 语句

3.2.1 语法格式

3.2.2 语法说明

3.2.3 代码示例:根据数字判断星期

3.2.4 代码示例:case 穿透现象(省略 break)

3.2.5 支持 String 类型的示例(JDK 7+)

3.2.6 switch 语句的注意事项

(1)表达式类型限制

(2)case 常量值重复

(3)break 关键字不可省略(除非需要穿透)

(4)无法表达复杂条件

(5)嵌套 switch 不推荐

3.2.7 if-else 与 switch 的对比与选择

四、循环结构

4.1 while 循环

4.1.1 语法格式

4.1.2 语法说明

4.1.3 代码示例 1:打印 1-10 的数字

4.1.4 代码示例 2:计算 1-100 的和

4.1.5 代码示例 3:计算 5 的阶乘

4.1.6 代码示例 4:计算 1! + 2! + 3! + 4! + 5!

4.1.7 while 循环的注意事项

(1)循环变量初始化

(2)循环变量更新(避免死循环)

(3)分号问题(常见错误)

(4)代码风格规范

4.2 break 关键字

4.2.1 语法格式

4.2.2 代码示例 1:找到 100-200 中第一个 3 的倍数

4.2.3 代码示例 2:break 在 for 循环中使用

4.2.4 代码示例 3:break 在嵌套循环中使用(仅终止当前循环)

4.3 continue 关键字

4.3.1 语法格式

4.3.2 代码示例 1:找到 100-200 中所有 3 的倍数

4.3.2 代码示例 2:continue 在 for 循环中使用(跳过偶数)

4.3.3 break 与 continue 的对比

4.4 for 循环

4.4.1 语法格式

4.4.2 语法说明

4.4.3 执行流程

4.4.4 代码示例 1:打印 1-10 的数字

4.4.5 代码示例 2:计算 1-100 的和

4.4.6 代码示例 3:计算 5 的阶乘

4.4.7 代码示例 4:计算 1! + 2! + 3! + 4! + 5!

4.4.8 for 循环的变体形式

(1)省略表达式①(循环变量已在外部初始化)

(2)省略表达式③(循环变量在循环体内更新)

(3)省略表达式①和③(等价于 while 循环)

(4)无限循环(省略所有表达式)

4.4.9 for 循环的注意事项

(1)循环变量的作用域

(2)分号问题(常见错误)

(3)循环条件的边界值

(4)避免在循环体内修改循环变量

4.5 do-while 循环(选学)

4.5.1 语法格式

4.5.2 语法说明

4.5.3 执行流程

4.5.4 代码示例:打印 1-10 的数字

4.5.5 代码示例:至少执行一次的场景(如用户输入验证)

4.5.6 do-while 循环的注意事项

(1)不要忘记末尾的分号

(2)循环变量更新位置

(3)适用场景有限

4.6 三种循环结构的对比与选择

五、Java 输入输出机制

5.1 控制台输出

5.1.1 三种输出方法对比

5.1.2 代码示例 1:println 与 print 的使用

5.1.3 代码示例 2:printf 格式化输出(重点)

常用转换符表

格式化输出示例

5.1.4 输出方法的注意事项

5.2 控制台输入

5.2.1 Scanner 类的使用步骤

5.2.2 常用输入方法

5.2.3 代码示例 1:读取基本类型数据

5.2.4 代码示例 2:循环读取多个整数并计算平均值

5.2.5 Scanner 类的注意事项

next () 与 nextLine () 的区别


前言

小编作为新晋码农一枚,会定期整理一些写的比较好的代码,作为自己的学习笔记,会试着做一下批注和补充,如转载或者参考他人文献会标明出处,非商用,如有侵权会删改!欢迎大家斧正和讨论!

程序的逻辑控制是编程的核心骨架,如同人类生活的行为准则 —— 顺序执行日常事务、根据选择决定方向、通过重复积累成果。Java 作为一门面向对象的编程语言,其逻辑控制语句不仅遵循通用编程思想,还具备自身独特的语法规范和最佳实践。

本文基于 Java 基础语法体系,围绕逻辑控制的三大核心(顺序结构、分支结构、循环结构)、输入输出机制及实战案例展开,总字数超 2 万字,涵盖语法细节、注意事项、代码示例、常见错误及优化方案,既是零基础学习者的入门指南,也是进阶开发者的查漏补缺手册。

通过本文学习,你将掌握 Java 程序的执行流程控制方法,能够灵活运用分支判断处理复杂条件,通过循环结构简化重复操作,熟练实现控制台的输入输出交互,并最终通过猜数字游戏等实战案例巩固所学知识,为后续面向对象编程、算法实现等内容奠定坚实基础。

一、程序逻辑控制概述

1.1 程序执行流程的本质

程序的执行流程本质上是指令的有序集合,如同人类的生活轨迹 —— 从起床到睡觉,每一步都有其先后顺序、选择判断和重复行为。Java 程序的执行流程主要分为三种基本结构,这三种结构可以组合实现任意复杂的程序逻辑:

  • 顺序结构:按代码书写顺序依次执行,是程序的基础骨架;
  • 分支结构:根据条件判断结果选择不同的执行路径,对应生活中的 "选择";
  • 循环结构:在条件满足时重复执行某段代码,对应生活中的 "重复"。

1.2 逻辑控制的重要性

  • 决定程序的执行路径:通过逻辑控制,程序能够根据不同场景执行不同代码,实现多样化功能;
  • 优化代码效率:合理的循环结构可以减少重复代码,分支结构可以避免无效执行;
  • 实现交互与响应:结合输入输出,逻辑控制使程序能够响应用户操作,完成动态任务;
  • 为复杂功能奠基:任何复杂的算法(如排序、搜索)、业务逻辑(如用户登录、数据验证)都依赖逻辑控制实现。

1.3 学习目标与核心内容

1.3.1 核心学习目标

  1. 掌握 Java 中顺序结构、分支结构(if-else、switch)、循环结构(while、for、do-while)的语法与使用场景;
  2. 熟练运用 break、continue 关键字控制循环流程;
  3. 掌握 Java 控制台输入输出的多种方式,包括普通输出、格式化输出及 Scanner 输入;
  4. 能够通过逻辑控制语句实现复杂条件判断、重复操作及交互功能;
  5. 完成猜数字游戏等实战案例,提升代码综合运用能力。

1.3.2 笔记核心框架

本文将按照 "理论基础→语法详解→代码示例→注意事项→实战应用" 的逻辑展开,每个知识点均配备详细的语法说明、多角度代码示例及常见问题分析,确保内容全面且易于理解。

二、顺序结构

2.1 顺序结构的定义与特点

顺序结构是 Java 程序中最基本、最简单的执行结构,其核心特点是:代码按照书写顺序从上到下依次执行,没有跳转、判断或重复

就像生活中 "起床→洗漱→吃早饭" 的固定流程,顺序结构中每一条语句都会被执行,且仅执行一次。顺序结构是程序的基础,所有复杂的程序逻辑都是在顺序结构的基础上,通过分支和循环结构进行扩展。

2.2 语法格式与代码示例

2.2.1 基本语法格式

顺序结构不需要特殊的关键字,只需将代码按执行顺序依次书写即可:

// 语句1
// 语句2
// 语句3
// ...

2.2.2 基础示例:顺序输出字符串

public class SequenceDemo1 {
    public static void main(String[] args) {
        System.out.println("aaa");
        System.out.println("bbb");
        System.out.println("ccc");
    }
}

运行结果

aaa
bbb
ccc

2.2.3 示例说明

上述代码中,三条System.out.println语句按书写顺序依次执行,先输出 "aaa",再输出 "bbb",最后输出 "ccc"。执行顺序与代码书写顺序完全一致,这就是顺序结构的核心特征。

2.2.4 扩展示例:变量运算的顺序执行

public class SequenceDemo2 {
    public static void main(String[] args) {
        // 步骤1:定义变量并赋值
        int a = 10;
        int b = 20;
        
        // 步骤2:执行运算
        int sum = a + b;
        int difference = b - a;
        int product = a * b;
        int quotient = b / a;
        
        // 步骤3:输出结果
        System.out.println("a + b = " + sum);
        System.out.println("b - a = " + difference);
        System.out.println("a * b = " + product);
        System.out.println("b / a = " + quotient);
    }
}

运行结果

a + b = 30
b - a = 10
a * b = 200
b / a = 2

示例说明:代码按 "定义变量→运算→输出" 的顺序执行,每一步都依赖前一步的结果。如果调整代码顺序,比如先输出再运算,会导致编译错误,因为变量在使用前未定义或未赋值。

2.3 顺序结构的调整与影响

顺序结构的执行顺序完全由代码书写顺序决定,调整代码顺序会直接改变程序的执行结果。

2.3.1 调整顺序后的示例

public class SequenceDemo3 {
    public static void main(String[] args) {
        System.out.println("aaa");
        System.out.println("ccc");
        System.out.println("bbb");
    }
}

运行结果

aaa
ccc
bbb

2.3.2 错误顺序示例(编译报错)

public class SequenceErrorDemo {
    public static void main(String[] args) {
        // 错误:先使用变量,后定义变量
        System.out.println("a + b = " + sum);
        int a = 10;
        int b = 20;
        int sum = a + b;
    }
}

编译错误信息

Error:(4, 36) java: 找不到符号
  符号:   变量 sum
  位置: 类 SequenceErrorDemo

错误原因:Java 程序执行时,变量必须先定义(声明),再赋值,最后才能使用。顺序结构的不可逆性要求我们在编写代码时,严格遵循 "先定义、后使用" 的原则。

2.4 顺序结构的应用场景

顺序结构是所有程序的基础,几乎所有功能的实现都离不开顺序结构,常见应用场景包括:

  • 变量的定义与初始化;
  • 简单的运算操作;
  • 连续的输出操作;
  • 方法的顺序调用;
  • 数据的简单处理(如赋值、类型转换)。

2.5 顺序结构的注意事项

  1. 变量声明与使用顺序:必须先声明变量,再赋值,最后使用,否则会导致编译错误;
  2. 代码执行的不可逆性:顺序结构中语句一旦执行完毕,无法回溯,如需重复执行需借助循环结构;
  3. 代码可读性:即使是顺序结构,也应通过缩进、注释等方式保证代码整洁,便于阅读;
  4. 避免冗余代码:顺序执行的代码中,不应包含无效语句(如未使用的变量赋值、重复的输出语句)。

三、分支结构

分支结构是程序根据条件判断结果选择不同执行路径的结构,对应生活中的 "选择"—— 比如 "如果考试及格,就出去玩;否则,在家学习"。Java 中的分支结构主要包括if-else语句和switch语句,分别适用于不同的条件判断场景。

3.1 if-else 语句

if-else语句是 Java 中最灵活、最常用的分支结构,能够处理简单条件、多重条件等复杂场景,支持布尔表达式的任意组合判断。

3.1.1 语法格式 1:单分支 if 语句

语法结构
if (布尔表达式) {
    // 语句块(布尔表达式为true时执行)
}
语法说明
  • 布尔表达式:结果只能是truefalse的表达式,可由关系运算符(>、<、>=、<=、==、!=)、逻辑运算符(&&、||、!)等组合构成;
  • 语句块:由一对{}包裹的一条或多条语句,当布尔表达式结果为true时,执行该语句块;若为false,则跳过该语句块,执行后续代码;
  • 若语句块中只有一条语句,{}可以省略,但不推荐(影响代码可读性和扩展性)。
代码示例:成绩奖励判断
public class IfDemo1 {
    public static void main(String[] args) {
        int score = 92;
        // 布尔表达式:score >= 90,结果为true
        if (score >= 90) {
            System.out.println("吃个大鸡腿!!!");
        }
        System.out.println("判断结束");
    }
}

运行结果

吃个大鸡腿!!!
判断结束
变体示例(布尔表达式为 false)
public class IfDemo1_2 {
    public static void main(String[] args) {
        int score = 85;
        if (score >= 90) {
            System.out.println("吃个大鸡腿!!!");
        }
        System.out.println("判断结束");
    }
}

运行结果

判断结束

3.1.2 语法格式 2:双分支 if-else 语句

语法结构
if (布尔表达式) {
    // 语句块1(布尔表达式为true时执行)
} else {
    // 语句块2(布尔表达式为false时执行)
}
语法说明
  • 布尔表达式结果为true时,执行语句块 1;为false时,执行语句块 2;
  • 语句块 1 和语句块 2 是互斥的,必然会执行且仅执行其中一个;
  • else不能单独使用,必须紧跟在if的语句块之后。
代码示例:成绩奖惩判断
public class IfElseDemo1 {
    public static void main(String[] args) {
        int score = 85;
        if (score >= 90) {
            System.out.println("吃个大鸡腿!!!");
        } else {
            System.out.println("挨大嘴巴子!!!");
        }
        System.out.println("判断结束");
    }
}

运行结果

挨大嘴巴子!!!
判断结束
练习 1:判断奇数偶数
public class IfElseDemo2 {
    public static void main(String[] args) {
        int num = 10;
        if (num % 2 == 0) {
            System.out.println("num 是偶数");
        } else {
            System.out.println("num 是奇数");
        }
    }
}

运行结果

num 是偶数
练习 2:判断正数、负数或零
public class IfElseDemo3 {
    public static void main(String[] args) {
        int num = -5;
        if (num > 0) {
            System.out.println("正数");
        } else if (num < 0) {
            System.out.println("负数");
        } else {
            System.out.println("0");
        }
    }
}

运行结果

负数

3.1.3 语法格式 3:多重分支 if-else if-else 语句

语法结构
if (布尔表达式1) {
    // 语句块1(表达式1为true时执行)
} else if (布尔表达式2) {
    // 语句块2(表达式1为false,表达式2为true时执行)
} else if (布尔表达式3) {
    // 语句块3(表达式1、2为false,表达式3为true时执行)
} ... {
    // 更多else if分支
} else {
    // 语句块n(所有表达式都为false时执行)
}
语法说明
  • 多重分支用于处理多个互斥条件,按表达式顺序依次判断;
  • 一旦某个布尔表达式为true,执行对应的语句块后,直接跳出整个if-else if-else结构,不再判断后续表达式;
  • else分支是可选的,用于处理所有条件都不满足的默认情况。
代码示例:成绩等级判断
public class IfElseIfDemo1 {
    public static void main(String[] args) {
        int score = 78;
        if (score >= 90 && score <= 100) {
            System.out.println("优秀");
        } else if (score >= 80 && score < 90) {
            System.out.println("良好");
        } else if (score >= 70 && score < 80) {
            System.out.println("中等");
        } else if (score >= 60 && score < 70) {
            System.out.println("及格");
        } else if (score >= 0 && score < 60) {
            System.out.println("不及格");
        } else {
            System.out.println("错误数据");
        }
    }
}

运行结果

中等
练习 3:判断闰年

闰年的判断规则:

  1. 能被 400 整除的年份是闰年;
  2. 能被 100 整除但不能被 400 整除的年份不是闰年;
  3. 能被 4 整除但不能被 100 整除的年份是闰年;
  4. 不能被 4 整除的年份不是闰年。
public class IfElseIfDemo2 {
    public static void main(String[] args) {
        int year = 2000;
        if (year % 100 == 0) {
            // 世纪闰年:能被100整除的年份,需判断是否能被400整除
            if (year % 400 == 0) {
                System.out.println("是闰年");
            } else {
                System.out.println("不是闰年");
            }
        } else {
            // 普通闰年:能被4整除且不能被100整除
            if (year % 4 == 0) {
                System.out.println("是闰年");
            } else {
                System.out.println("不是闰年");
            }
        }
    }
}

运行结果

是闰年

3.1.4 if 语句的嵌套

语法结构
if (外层布尔表达式) {
    // 外层语句块
    if (内层布尔表达式) {
        // 内层语句块1
    } else {
        // 内层语句块2
    }
} else {
    // 外层else语句块
}
语法说明
  • 嵌套if语句是指在一个ifelse语句块中包含另一个if-else结构;
  • 内层if的判断依赖外层if的结果,只有外层条件满足时,才会执行内层判断;
  • 嵌套层级没有限制,但层级过多会影响代码可读性,建议不超过 3 层。
代码示例:嵌套判断学生成绩与性别
public class NestedIfDemo {
    public static void main(String[] args) {
        int score = 95;
        String gender = "男";
        
        if (score >= 90) {
            System.out.println("成绩优秀,获得奖励");
            if (gender.equals("男")) {
                System.out.println("奖励篮球一个");
            } else {
                System.out.println("奖励跳绳一根");
            }
        } else {
            System.out.println("继续努力");
        }
    }
}

运行结果

成绩优秀,获得奖励
奖励篮球一个

3.1.5 if 语句的注意事项

(1)代码风格规范

Java 推荐的代码风格(风格 1):

int x = 10;
if (x == 10) {
    // 语句1
} else {
    // 语句2
}

不推荐的风格(风格 2):

int x = 10;
if (x == 10)
{
    // 语句1
}
else
{
    // 语句2
}

推荐理由

  • 风格 1 的{if/else同行,代码更紧凑,节省空间;
  • 风格 1 的缩进更清晰,便于区分语句块层级;
  • 符合 Java 社区的编码规范,提高代码可读性和协作效率。
(2)分号问题(常见错误)

错误示例:

public class IfSemicolonError {
    public static void main(String[] args) {
        int x = 20;
        if (x == 10); // 此处多写了分号
        {
            System.out.println("hehe");
        }
    }
}

运行结果

hehe

错误原因

  • Java 中,分号;表示一条语句的结束;
  • 上述代码中,if (x == 10); 中的分号导致if语句的语句体为空,后续的{}块与if无关,成为独立的代码块,无论if条件是否满足都会执行。
(3)悬垂 else 问题

错误示例:

public class DanglingElseDemo {
    public static void main(String[] args) {
        int x = 10;
        int y = 5;
        if (x == 10) 
            if (y == 10)
                System.out.println("aaa");
            else 
                System.out.println("bbb");
    }
}

运行结果

bbb

问题分析

  • 上述代码中,else没有明确的匹配对象,Java 规定else总是与最近的未匹配的if配对;
  • 虽然代码缩进显示else想与外层if配对,但实际执行时else与内层if配对,导致逻辑与预期不符。

解决方案:无论语句块中是否只有一条语句,都加上{}明确语句块范围:

public class CorrectDanglingElse {
    public static void main(String[] args) {
        int x = 10;
        int y = 5;
        if (x == 10) {
            if (y == 10) {
                System.out.println("aaa");
            }
        } else {
            System.out.println("bbb");
        }
    }
}

运行结果

(无输出,因为外层if条件满足,内层if条件不满足)
(4)布尔表达式的简化

冗余的布尔表达式:

// 冗余写法
if (score >= 60 && score <= 100) { ... }
if (flag == true) { ... }
if (num != 0) { ... }

简化后的布尔表达式:

// 简化写法(效果相同,更简洁)
if (score >= 60) { ... } // 前提:score已验证不超过100
if (flag) { ... }
if (num != 0) { ... } // 无法简化,保持原样即可
(5)变量作用域问题
public class IfScopeError {
    public static void main(String[] args) {
        int x = 10;
        if (x > 5) {
            int y = 20; // y的作用域仅限于if语句块内
            System.out.println(y);
        }
        System.out.println(y); // 错误:无法访问y,超出作用域
    }
}

编译错误信息

Error:(8, 22) java: 找不到符号
  符号:   变量 y
  位置: 类 IfScopeError

注意事项

  • if语句块内定义的变量,作用域仅限于该语句块;
  • 若需在语句块外使用变量,应在语句块外声明,块内赋值。

3.2 switch 语句

switch语句是另一种分支结构,适用于变量与多个常量值进行匹配的场景,相较于if-else if-else,代码结构更清晰,但灵活性较低。

3.2.1 语法格式

switch (表达式) {
    case 常量值1:
        // 语句块1
        break;
    case 常量值2:
        // 语句块2
        break;
    case 常量值3:
        // 语句块3
        break;
    ...
    case 常量值n:
        // 语句块n
        break;
    default:
        // 所有case都不匹配时执行的语句块
        break;
}

3.2.2 语法说明

  • 表达式:支持的类型包括byte、short、int、char(JDK 5 + 支持enum枚举,JDK 7 + 支持String字符串);
  • 常量值:每个case后的常量值必须是与表达式类型一致的字面量或常量,且不能重复;
  • break关键字:用于跳出switch结构,若省略break,会发生 "穿透" 现象(执行当前 case 后,继续执行后续 case 的语句块);
  • default分支:可选,用于处理所有case都不匹配的情况,位置可任意(建议放在最后),无需break(但加上更规范)。

3.2.3 代码示例:根据数字判断星期

public class SwitchDemo1 {
    public static void main(String[] args) {
        int day = 3;
        switch (day) {
            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("无效的日期");
                break;
        }
    }
}

运行结果

星期三

3.2.4 代码示例:case 穿透现象(省略 break)

public class SwitchBreakDemo {
    public static void main(String[] args) {
        int day = 1;
        switch (day) {
            case 1:
                System.out.println("星期一");
                // 省略break,发生穿透
            case 2:
                System.out.println("星期二");
                break;
            case 3:
                System.out.println("星期三");
                break;
            default:
                System.out.println("无效的日期");
                break;
        }
    }
}

运行结果

星期一
星期二

穿透现象的合理应用:当多个case需要执行相同的语句块时,可利用穿透现象简化代码:

public class SwitchPenetrationDemo {
    public static void main(String[] args) {
        int month = 2;
        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;
            default:
                System.out.println("无效的月份");
                break;
        }
    }
}

运行结果

冬季

3.2.5 支持 String 类型的示例(JDK 7+)

public class SwitchStringDemo {
    public static void main(String[] args) {
        String fruit = "苹果";
        switch (fruit) {
            case "苹果":
                System.out.println("苹果的价格是5元/斤");
                break;
            case "香蕉":
                System.out.println("香蕉的价格是3元/斤");
                break;
            case "橙子":
                System.out.println("橙子的价格是4元/斤");
                break;
            default:
                System.out.println("暂无该水果价格");
                break;
        }
    }
}

运行结果

苹果的价格是5元/斤

3.2.6 switch 语句的注意事项

(1)表达式类型限制

switch的表达式不能是long、float、double、boolean等类型,否则会编译错误:

public class SwitchTypeError {
    public static void main(String[] args) {
        double num = 1.0;
        switch (num) { // 编译错误:不兼容的类型
            case 1.0:
                System.out.println("hehe");
                break;
            case 2.0:
                System.out.println("haha");
                break;
        }
    }
}

编译错误信息

Error:(4, 15) java: 不兼容的类型: 从double转换到int可能会有损失
(2)case 常量值重复

case后的常量值必须唯一,否则编译错误:

public class SwitchDuplicateCaseError {
    public static void main(String[] args) {
        int num = 1;
        switch (num) {
            case 1:
                System.out.println("hehe");
                break;
            case 1: // 编译错误:重复的case标签
                System.out.println("haha");
                break;
        }
    }
}

编译错误信息

Error:(6, 13) java: 重复的case标签
(3)break 关键字不可省略(除非需要穿透)

若无意省略break,会导致逻辑错误,比如:

public class SwitchMissingBreakError {
    public static void main(String[] args) {
        int score = 85;
        switch (score / 10) {
            case 9:
                System.out.println("优秀");
            case 8:
                System.out.println("良好");
            case 7:
                System.out.println("中等");
            case 6:
                System.out.println("及格");
            default:
                System.out.println("不及格");
        }
    }
}

运行结果

良好
中等
及格
不及格

错误原因score / 10 = 8,匹配case 8后,因无break,依次穿透执行case 7、case 6、default的语句块。

(4)无法表达复杂条件

switch仅支持 "变量 == 常量值" 的判断,无法表达范围条件(如num > 10 && num < 20),这类场景需使用if-else if-else

// 以下逻辑无法用switch实现,只能用if
int num = 15;
if (num > 10 && num < 20) {
    System.out.println("hehe");
}
(5)嵌套 switch 不推荐

switch支持嵌套,但会严重影响代码可读性,不推荐使用:

public class NestedSwitchDemo {
    public static void main(String[] args) {
        int x = 1;
        int y = 1;
        switch (x) {
            case 1:
                switch (y) {
                    case 1:
                        System.out.println("hehe");
                        break;
                    case 2:
                        System.out.println("haha");
                        break;
                }
                break;
            case 2:
                System.out.println("x=2");
                break;
        }
    }
}

3.2.7 if-else 与 switch 的对比与选择

特性if-else 语句switch 语句
适用场景复杂条件判断(范围、逻辑组合)简单等值判断(变量与常量匹配)
灵活性高,支持任意布尔表达式低,仅支持特定类型的等值判断
代码可读性条件较少时清晰,条件较多时繁琐条件较多时更清晰,结构规整
执行效率依次判断,最坏情况需遍历所有条件基于跳转表,效率较高(条件越多越明显)
维护成本条件修改时需调整表达式,成本较高新增条件只需添加 case,成本较低

选择建议

  • 当条件是 "变量与多个常量值匹配" 时,优先使用switch,代码更简洁;
  • 当条件是范围判断、逻辑组合判断(如num > 10 && num < 20)时,必须使用if-else if-else
  • 当条件数量较少(3 个以内)时,if-elseswitch均可,推荐if-else(无需记忆 break)。

四、循环结构

循环结构是程序在条件满足时重复执行某段代码的结构,对应生活中的 "重复"—— 比如 "每天刷题 1 小时"、"每周运动 3 次"。Java 中的循环结构主要包括while循环、for循环和do-while循环,其中for循环和while循环最为常用。

4.1 while 循环

while循环是最基础的循环结构,语法简洁,适用于循环次数不确定但循环条件明确的场景。

4.1.1 语法格式

while (循环条件) {
    // 循环体(条件满足时执行的代码块)
}

4.1.2 语法说明

  • 循环条件:布尔表达式,结果为true时执行循环体,为false时结束循环;
  • 循环体:由{}包裹的一条或多条语句,负责实现循环的核心逻辑;
  • 执行流程:先判断循环条件,再执行循环体(条件不满足时,循环体一次都不执行);
  • 若循环体中只有一条语句,{}可以省略,但不推荐。

4.1.3 代码示例 1:打印 1-10 的数字

public class WhileDemo1 {
    public static void main(String[] args) {
        int num = 1; // 循环变量初始化
        while (num <= 10) { // 循环条件:num≤10时执行循环
            System.out.println(num); // 循环体:打印num
            num++; // 循环变量更新(避免死循环)
        }
    }
}

运行结果

1
2
3
4
5
6
7
8
9
10

4.1.4 代码示例 2:计算 1-100 的和

public class WhileDemo2 {
    public static void main(String[] args) {
        int n = 1; // 循环变量(从1开始)
        int sum = 0; // 累加和变量(初始值为0)
        while (n <= 100) {
            sum += n; // 累加:sum = sum + n
            n++; // 循环变量更新
        }
        System.out.println("1-100的和为:" + sum);
    }
}

运行结果

1-100的和为:5050

4.1.5 代码示例 3:计算 5 的阶乘

阶乘定义:n! = n × (n-1) × (n-2) × ... × 1(0! = 1)

public class WhileDemo3 {
    public static void main(String[] args) {
        int n = 1; // 循环变量
        int result = 1; // 阶乘结果(初始值为1,乘法的单位元)
        while (n <= 5) {
            result *= n; // 累乘:result = result × n
            n++; // 循环变量更新
        }
        System.out.println("5的阶乘为:" + result);
    }
}

运行结果

5的阶乘为:120

4.1.6 代码示例 4:计算 1! + 2! + 3! + 4! + 5!

public class WhileDemo4 {
    public static void main(String[] args) {
        int num = 1; // 外层循环变量:控制阶乘的个数(1!到5!)
        int sum = 0; // 阶乘和变量
        while (num <= 5) {
            int factorResult = 1; // 单个阶乘的结果(每次循环重置为1)
            int tmp = 1; // 内层循环变量:计算单个阶乘
            // 内层循环:计算num的阶乘
            while (tmp <= num) {
                factorResult *= tmp;
                tmp++;
            }
            sum += factorResult; // 将当前阶乘结果累加到总和
            num++; // 外层循环变量更新
        }
        System.out.println("1! + 2! + 3! + 4! + 5! = " + sum);
    }
}

运行结果

1! + 2! + 3! + 4! + 5! = 153

4.1.7 while 循环的注意事项

(1)循环变量初始化

循环变量必须在循环前初始化,否则会编译错误:

public class WhileInitError {
    public static void main(String[] args) {
        while (num <= 10) { // 编译错误:num未初始化
            System.out.println(num);
            num++;
        }
    }
}

编译错误信息

Error:(3, 17) java: 找不到符号
  符号:   变量 num
  位置: 类 WhileInitError
(2)循环变量更新(避免死循环)

循环体中必须包含循环变量的更新语句(如num++),否则循环条件会永远为true,导致死循环:

public class WhileInfiniteLoopError {
    public static void main(String[] args) {
        int num = 1;
        while (num <= 10) {
            System.out.println(num);
            // 缺少num++,循环变量永远为1,条件永远成立
        }
    }
}

运行结果

1
1
1
...(无限循环输出1,需手动终止程序)
(3)分号问题(常见错误)

while循环条件后不能多加分号,否则分号会成为循环体(空语句),导致循环无法正确执行:

public class WhileSemicolonError {
    public static void main(String[] args) {
        int num = 1;
        while (num <= 10); { // 分号导致循环体为空
            System.out.println(num);
            num++;
        }
    }
}

运行结果

(无输出,程序死循环)

错误原因while (num <= 10); 中的分号表示循环体为空,后续的{}块与循环无关。由于num始终为 1,循环条件永远成立,程序进入死循环,无法执行{}块中的代码。

(4)代码风格规范

if语句一致,while循环的{推荐与while同行,循环体缩进清晰:

// 推荐风格
int num = 1;
while (num <= 10) {
    System.out.println(num);
    num++;
}

// 不推荐风格
int num = 1;
while (num <= 10)
{
    System.out.println(num);
    num++;
}

4.2 break 关键字

break关键字用于终止当前所在的循环(while、for、do-while)或 switch 语句,使程序跳转到循环或 switch 之后的代码继续执行。

4.2.1 语法格式

// 在循环或switch中使用
break;

4.2.2 代码示例 1:找到 100-200 中第一个 3 的倍数

public class BreakDemo1 {
    public static void main(String[] args) {
        int num = 100;
        while (num <= 200) {
            if (num % 3 == 0) {
                System.out.println("找到了3的倍数,为:" + num);
                break; // 找到后终止循环,不再继续查找
            }
            num++;
        }
    }
}

运行结果

找到了3的倍数,为:102

说明:当num=102时,num%3==0条件成立,执行break语句,while循环立即终止,程序跳出循环继续执行后续代码(此处无后续代码,程序结束)。

4.2.3 代码示例 2:break 在 for 循环中使用

public class BreakDemo2 {
    public static void main(String[] args) {
        for (int i = 1; i <= 10; i++) {
            if (i == 5) {
                break; // i=5时终止循环
            }
            System.out.println(i);
        }
    }
}

运行结果

1
2
3
4

4.2.4 代码示例 3:break 在嵌套循环中使用(仅终止当前循环)

break仅终止其所在的最内层循环,外层循环不受影响:

public class BreakNestedDemo {
    public static void main(String[] args) {
        // 外层循环:控制行数
        for (int i = 1; i <= 3; i++) {
            // 内层循环:控制列数
            for (int j = 1; j <= 3; j++) {
                if (j == 2) {
                    break; // 仅终止内层循环
                }
                System.out.print(j + " ");
            }
            System.out.println(); // 换行
        }
    }
}

运行结果

1 
1 
1 

说明:当j=2时,break终止内层循环,外层循环继续执行下一次迭代(i=2、i=3)。

4.3 continue 关键字

continue关键字用于跳过当前循环的剩余语句,直接进入下一次循环,不会终止整个循环。

4.3.1 语法格式

// 在循环中使用
continue;

4.3.2 代码示例 1:找到 100-200 中所有 3 的倍数

public class ContinueDemo1 {
    public static void main(String[] args) {
        int num = 100;
        while (num <= 200) {
            if (num % 3 != 0) {
                num++; // 必须先更新循环变量,否则会死循环
                continue; // 跳过当前循环的剩余语句,进入下一次循环
            }
            System.out.println("找到了3的倍数,为:" + num);
            num++;
        }
    }
}

运行结果(部分)

找到了3的倍数,为:102
找到了3的倍数,为:105
找到了3的倍数,为:108
...(直到200以内的最后一个3的倍数198)

说明

  • num%3!=0时,执行continue语句,跳过后续的System.out.println语句,直接进入下一次循环判断;
  • 注意:continue之前必须更新循环变量(num++),否则循环变量永远不变,导致死循环。

4.3.2 代码示例 2:continue 在 for 循环中使用(跳过偶数)

public class ContinueDemo2 {
    public static void main(String[] args) {
        for (int i = 1; i <= 10; i++) {
            if (i % 2 == 0) {
                continue; // 跳过偶数,进入下一次循环
            }
            System.out.println(i);
        }
    }
}

运行结果

1
3
5
7
9

4.3.3 break 与 continue 的对比

关键字作用范围核心功能循环是否继续
break循环或 switch终止当前循环 /switch不再继续
continue仅循环跳过当前循环剩余语句,进入下一次循环继续执行

记忆口诀

  • break:"一刀两断",直接终止循环;
  • continue:"半途而废",跳过当前次,继续下一次。

4.4 for 循环

for循环是 Java 中最常用的循环结构,语法紧凑,将循环变量初始化、循环条件、循环变量更新集中在一处,适用于循环次数明确的场景。

4.4.1 语法格式

for (表达式①; 布尔表达式②; 表达式③) {
    // 循环体(表达式④)
}

4.4.2 语法说明

  • 表达式①:循环变量初始化,用于定义循环变量并赋初始值,仅在循环开始时执行一次
  • 布尔表达式②:循环条件,结果为true时执行循环体,为false时终止循环,每次循环前都会判断
  • 表达式③:循环变量更新,用于修改循环变量的值(如i++i--),每次循环体执行完毕后执行
  • 循环体(表达式④):条件满足时执行的代码块,可包含任意合法的 Java 语句。

4.4.3 执行流程

表达式① → 布尔表达式② → (true)循环体 → 表达式③ → 布尔表达式② → ... → (false)循环结束

具体步骤:

  1. 执行表达式①(初始化循环变量);
  2. 判断布尔表达式②:
    • 若为false,循环终止,执行循环后的代码;
    • 若为true,执行循环体;
  3. 循环体执行完毕后,执行表达式③(更新循环变量);
  4. 回到步骤 2,重复判断和执行,直到布尔表达式②为false

4.4.4 代码示例 1:打印 1-10 的数字

public class ForDemo1 {
    public static void main(String[] args) {
        // 表达式①:i=1(初始化循环变量)
        // 表达式②:i<=10(循环条件)
        // 表达式③:i++(循环变量更新)
        for (int i = 1; i <= 10; i++) {
            System.out.println(i); // 循环体
        }
    }
}

运行结果

1
2
3
4
5
6
7
8
9
10

4.4.5 代码示例 2:计算 1-100 的和

public class ForDemo2 {
    public static void main(String[] args) {
        int sum = 0;
        for (int i = 1; i <= 100; i++) {
            sum += i; // 累加:sum = sum + i
        }
        System.out.println("1-100的和为:" + sum);
    }
}

运行结果

1-100的和为:5050

4.4.6 代码示例 3:计算 5 的阶乘

public class ForDemo3 {
    public static void main(String[] args) {
        int result = 1;
        for (int i = 1; i <= 5; i++) {
            result *= i; // 累乘:result = result × i
        }
        System.out.println("5的阶乘为:" + result);
    }
}

运行结果

5的阶乘为:120

4.4.7 代码示例 4:计算 1! + 2! + 3! + 4! + 5!

public class ForDemo4 {
    public static void main(String[] args) {
        int sum = 0;
        // 外层循环:控制阶乘的个数(1!到5!)
        for (int i = 1; i <= 5; i++) {
            int tmp = 1;
            // 内层循环:计算i的阶乘
            for (int j = 1; j <= i; j++) {
                tmp *= j;
            }
            sum += tmp; // 累加当前阶乘结果
        }
        System.out.println("1! + 2! + 3! + 4! + 5! = " + sum);
    }
}

运行结果

1! + 2! + 3! + 4! + 5! = 153

4.4.8 for 循环的变体形式

(1)省略表达式①(循环变量已在外部初始化)
public class ForVariant1 {
    public static void main(String[] args) {
        int i = 1; // 循环变量在外部初始化
        for (; i <= 10; i++) { // 省略表达式①,分号不能省略
            System.out.println(i);
        }
    }
}
(2)省略表达式③(循环变量在循环体内更新)
public class ForVariant2 {
    public static void main(String[] args) {
        for (int i = 1; i <= 10; ) { // 省略表达式③,分号不能省略
            System.out.println(i);
            i++; // 循环变量在循环体内更新
        }
    }
}
(3)省略表达式①和③(等价于 while 循环)
public class ForVariant3 {
    public static void main(String[] args) {
        int i = 1;
        for (; i <= 10; ) { // 省略表达式①和③
            System.out.println(i);
            i++;
        }
        // 等价于:
        // while (i <= 10) {
        //     System.out.println(i);
        //     i++;
        // }
    }
}
(4)无限循环(省略所有表达式)
public class ForInfiniteLoop {
    public static void main(String[] args) {
        // 省略所有表达式,分号不能省略
        for (;;) {
            System.out.println("无限循环");
            // 需在循环体内添加break终止循环,否则会一直执行
            // break;
        }
    }
}

说明:无限循环需在循环体内通过break等方式终止,否则程序会一直运行直到手动终止。

4.4.9 for 循环的注意事项

(1)循环变量的作用域

for循环的循环变量(表达式①中定义的变量)作用域仅限于循环体内,循环结束后无法访问:

public class ForScopeDemo {
    public static void main(String[] args) {
        for (int i = 1; i <= 10; i++) {
            System.out.println(i);
        }
        System.out.println(i); // 编译错误:i超出作用域
    }
}

编译错误信息

Error:(6, 22) java: 找不到符号
  符号:   变量 i
  位置: 类 ForScopeDemo
(2)分号问题(常见错误)

for循环的表达式之间必须用分号分隔,且不能多加分号:

public class ForSemicolonError {
    public static void main(String[] args) {
        // 错误:多加分号,导致循环体为空
        for (int i = 1; i <= 10; i++); {
            System.out.println(i); // 编译错误:i超出作用域
        }
    }
}

错误原因for (int i = 1; i <= 10; i++); 中的分号使循环体为空,后续的{}块与循环无关,且i的作用域仅限于for循环,无法在{}块中访问。

(3)循环条件的边界值

循环条件的边界值错误会导致循环次数异常,比如:

public class ForBoundaryError {
    public static void main(String[] args) {
        // 错误:循环条件为i < 10,少执行一次(未打印10)
        for (int i = 1; i < 10; i++) {
            System.out.println(i);
        }
    }
}

运行结果

1
2
...
9

解决方案:根据需求明确边界值,如需打印 1-10,循环条件应改为i <= 10

(4)避免在循环体内修改循环变量

在循环体内修改循环变量可能导致逻辑混乱,比如:

public class ForModifyVarError {
    public static void main(String[] args) {
        for (int i = 1; i <= 10; i++) {
            System.out.println(i);
            i++; // 循环体内修改循环变量,导致步长为2
        }
    }
}

运行结果

1
3
5
7
9

说明:循环变量的更新应统一在表达式③中进行,避免在循环体内随意修改,提高代码可读性和可维护性。

4.5 do-while 循环(选学)

do-while循环是 Java 中唯一的 "后判断" 循环结构,特点是先执行循环体,再判断循环条件,确保循环体至少执行一次。

4.5.1 语法格式

do {
    // 循环体
} while (循环条件);

4.5.2 语法说明

  • 循环体:先执行一次循环体,再判断循环条件;
  • 循环条件:布尔表达式,结果为true时继续执行循环体,为false时终止循环;
  • 循环体后必须加;,表示循环语句结束。

4.5.3 执行流程

循环体 → 循环条件 → (true)循环体 → 循环条件 → ... → (false)循环结束

4.5.4 代码示例:打印 1-10 的数字

public class DoWhileDemo1 {
    public static void main(String[] args) {
        int num = 1;
        do {
            System.out.println(num); // 先执行循环体
            num++; // 循环变量更新
        } while (num <= 10); // 后判断循环条件
    }
}

运行结果

1
2
3
4
5
6
7
8
9
10

4.5.5 代码示例:至少执行一次的场景(如用户输入验证)

import java.util.Scanner;

public class DoWhileDemo2 {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int password;
        do {
            System.out.println("请输入密码(6位数字):");
            password = sc.nextInt();
        } while (password < 100000 || password > 999999); // 密码不是6位数字时重新输入
        System.out.println("密码输入正确!");
        sc.close();
    }
}

运行结果

请输入密码(6位数字):
12345
请输入密码(6位数字):
123456
密码输入正确!

4.5.6 do-while 循环的注意事项

(1)不要忘记末尾的分号

do-while循环的while条件后必须加;,否则编译错误:

public class DoWhileSemicolonError {
    public static void main(String[] args) {
        int num = 1;
        do {
            System.out.println(num);
            num++;
        } while (num <= 10) // 编译错误:缺少分号
    }
}

编译错误信息

Error:(7, 35) java: 缺少';'
(2)循环变量更新位置

循环变量的更新应放在循环体内,否则会导致死循环:

public class DoWhileInfiniteLoopError {
    public static void main(String[] args) {
        int num = 1;
        do {
            System.out.println(num);
            // 缺少num++,循环变量永远为1,条件永远成立
        } while (num <= 10);
    }
}
(3)适用场景有限

do-while循环仅适用于 "循环体必须至少执行一次" 的场景(如输入验证、菜单选择),其他场景推荐使用forwhile循环,代码可读性更高。

4.6 三种循环结构的对比与选择

循环类型语法特点执行顺序适用场景
while 循环循环变量初始化、更新分散在循环外先判断条件,后执行循环体循环次数不确定,条件明确
for 循环初始化、条件、更新集中在一处先判断条件,后执行循环体循环次数明确(如固定次数的循环)
do-while 循环循环体后判断条件先执行循环体,后判断条件循环体必须至少执行一次(如输入验证)

选择建议

  • 当循环次数明确时(如打印 1-100、计算 n 的阶乘),优先使用for循环,代码更紧凑;
  • 当循环次数不确定,但循环条件明确时(如查找某个满足条件的元素),优先使用while循环;
  • 当循环体必须至少执行一次时(如用户输入验证、菜单系统),使用do-while循环;
  • 嵌套循环中,外层和内层可根据需求选择不同的循环类型,通常外层用for,内层用whilefor

五、Java 输入输出机制

输入输出(I/O)是程序与用户交互的核心方式,Java 提供了丰富的 I/O 工具类,其中控制台输入输出是最基础、最常用的功能,主要包括System.out相关的输出方法和Scanner类的输入方法。

5.1 控制台输出

Java 的控制台输出主要通过System.out对象实现,System.outPrintStream类的实例,提供了println()print()printf()三种常用输出方法,分别适用于不同的输出场景。

5.1.1 三种输出方法对比

方法名功能描述是否换行示例代码输出结果
println(msg)输出指定内容后,自动换行System.out.println("hello");System.out.println("world");helloworld
print(msg)输出指定内容,不自动换行System.out.print("hello ");System.out.print("world");hello world
printf(format, args)格式化输出,支持占位符替换int x = 10;System.out.printf("x = %d\n", x);x = 10

5.1.2 代码示例 1:println 与 print 的使用

public class OutputDemo1 {
    public static void main(String[] args) {
        // println:自动换行
        System.out.println("Hello Java");
        System.out.println("这是println输出");
        
        // print:不自动换行
        System.out.print("Hello ");
        System.out.print("World");
        System.out.print("\n"); // 手动换行(\n是换行符)
    }
}

运行结果

Hello Java
这是println输出
Hello World

5.1.3 代码示例 2:printf 格式化输出(重点)

printf方法支持通过占位符(转换符)格式化输出各种类型的数据,格式为:printf("格式化字符串", 参数1, 参数2, ...),其中格式化字符串包含普通字符和占位符。

常用转换符表
转换符对应数据类型功能描述示例代码输出结果
%d十进制整数输出整数的十进制表示System.out.printf("%d", 100);100
%x十六进制整数输出整数的十六进制表示(小写)System.out.printf("%x", 100);64
%o八进制整数输出整数的八进制表示System.out.printf("%o", 100);144
%f定点浮点数输出浮点数的定点表示(默认保留 6 位小数)System.out.printf("%f", 100.5);100.500000
%e指数浮点数输出浮点数的科学计数法表示System.out.printf("%e", 100.5);1.005000e+02
%g通用浮点数自动选择定点或指数表示,去除多余小数位System.out.printf("%g", 100.500);100.5
%s字符串输出字符串内容System.out.printf("%s", "Java");Java
%c字符输出单个字符System.out.printf("%c", 'A');A
%b布尔值输出 true 或 false(非 null 值均为 true)System.out.printf("%b", 100);true
%%百分号输出百分号(% 是特殊字符,需用 %% 转义)System.out.printf("%.2f%%", 2.0/7);0.29%
格式化输出示例
public class PrintfDemo {
    public static void main(String[] args) {
        // 整数格式化
        int a = 100;
        System.out.printf("十进制:%d\n", a);
        System.out.printf("十六进制:%x\n", a);
        System.out.printf("八进制:%o\n", a);
        
        // 浮点数格式化
        double b = 123.456;
        System.out.printf("默认浮点数:%f\n", b);
        System.out.printf("保留2位小数:%.2f\n", b);
        System.out.printf("科学计数法:%e\n", b);
        System.out.printf("通用格式:%g\n", b);
        
        // 字符串和字符格式化
        String str = "Java编程";
        char c = '中';
        System.out.printf("字符串:%s\n", str);
        System.out.printf("字符:%c\n", c);
        
        // 布尔值和百分号格式化
        boolean flag = true;
        double rate = 0.75;
        System.out.printf("布尔值:%b\n", flag);
        System.out.printf("百分比:%.2f%%\n", rate * 100);
        
        // 多参数格式化
        String name = "张三";
        int age = 20;
        double score = 95.5;
        System.out.printf("姓名:%s,年龄:%d,成绩:%.1f\n", name, age, score);
    }
}

运行结果

十进制:100
十六进制:64
八进制:144
默认浮点数:123.456000
保留2位小数:123.46
科学计数法:1.234560e+02
通用格式:123.456
字符串:Java编程
字符:中
布尔值:true
百分比:75.00%
姓名:张三,年龄:20,成绩:95.5

5.1.4 输出方法的注意事项

  • println()方法的参数可以是任意类型(基本类型、引用类型),若参数为null,会输出 "null";
  • print()方法与println()功能类似,仅缺少自动换行,需手动添加\n(换行符)或\r\n(Windows 系统换行符)实现换行;
  • printf()方法的格式化字符串中,占位符的数量必须与后续参数的数量一致,否则会抛出IllegalFormatArgumentCountException异常;
  • 浮点数格式化时,%.nf表示保留 n 位小数,会自动四舍五入(如%.2f格式化 123.456,结果为 123.46)。

5.2 控制台输入

Java 的控制台输入主要通过java.util.Scanner类实现,Scanner提供了丰富的方法用于读取不同类型的输入数据(整数、浮点数、字符串、字符等),是 Java SE 5 及以上版本的标准输入工具。

5.2.1 Scanner 类的使用步骤

  1. 导入Scanner类:import java.util.Scanner;(必须在类定义之前);
  2. 创建Scanner对象:Scanner sc = new Scanner(System.in);System.in表示标准输入流,即键盘输入);
  3. 调用Scanner的方法读取输入数据(如nextInt()nextDouble()nextLine()等);
  4. 关闭Scanner对象:sc.close();(释放资源,避免内存泄漏)。

5.2.2 常用输入方法

方法名功能描述输入示例代码示例
nextInt()读取下一个整数(int 类型)20int age = sc.nextInt();
nextLong()读取下一个长整数(long 类型)1000000000long num = sc.nextLong();
nextDouble()读取下一个双精度浮点数(double 类型)95.5double score = sc.nextDouble();
nextFloat()读取下一个单精度浮点数(float 类型)3.14ffloat pi = sc.nextFloat();
next()读取下一个字符串(以空白符为分隔符)HelloString str = sc.next();
nextLine()读取一整行字符串(以回车符为分隔符)Hello WorldString line = sc.nextLine();
nextChar()无此方法,需通过 next ().charAt (0) 读取单个字符Achar c = sc.next().charAt(0);
hasNextInt()判断输入是否为整数,返回 boolean 值-while (sc.hasNextInt()) { ... }

5.2.3 代码示例 1:读取基本类型数据

import java.util.Scanner;

public class ScannerDemo1 {
    public static void main(String[] args) {
        // 1. 创建Scanner对象
        Scanner sc = new Scanner(System.in);
        
        // 2. 读取输入数据
        System.out.println("请输入你的姓名:");
        String name = sc.nextLine(); // 读取字符串(整行)
        
        System.out.println("请输入你的年龄:");
        int age = sc.nextInt(); // 读取整数
        
        System.out.println("请输入你的身高(米):");
        double height = sc.nextDouble(); // 读取浮点数
        
        System.out.println("请输入你的性别(男/女):");
        char gender = sc.next().charAt(0); // 读取单个字符
        
        // 3. 输出读取到的数据
        System.out.println("\n你的信息如下:");
        System.out.printf("姓名:%s\n", name);
        System.out.printf("年龄:%d岁\n", age);
        System.out.printf("身高:%.2f米\n", height);
        System.out.printf("性别:%c\n", gender);
        
        // 4. 关闭Scanner对象
        sc.close();
    }
}

运行结果

请输入你的姓名:
张三
请输入你的年龄:
20
请输入你的身高(米):
1.75
请输入你的性别(男/女):
男

你的信息如下:
姓名:张三
年龄:20岁
身高:1.75米
性别:男

5.2.4 代码示例 2:循环读取多个整数并计算平均值

import java.util.Scanner;

public class ScannerDemo2 {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int sum = 0; // 总和
        int count = 0; // 输入的数字个数
        
        System.out.println("请输入多个整数(输入非整数结束):");
        // hasNextInt():判断下一个输入是否为整数
        while (sc.hasNextInt()) {
            int num = sc.nextInt();
            sum += num;
            count++;
        }
        
        // 计算平均值(注意避免除以0)
        if (count > 0) {
            double avg = (double) sum / count; // 强制类型转换,避免整数除法
            System.out.printf("输入的数字总和:%d\n", sum);
            System.out.printf("输入的数字个数:%d\n", count);
            System.out.printf("平均值:%.2f\n", avg);
        } else {
            System.out.println("未输入有效整数!");
        }
        
        sc.close();
    }
}

运行结果

请输入多个整数(输入非整数结束):
10 20 30 40 50 a
输入的数字总和:150
输入的数字个数:5
平均值:30.00

说明

  • hasNextInt()方法会阻塞程序,直到用户输入数据并按下回车;
  • 当输入非整数(如上述示例中的 "a")时,hasNextInt()返回false,循环终止;
  • Windows 系统中,也可通过Ctrl+Z(Linux/Mac 系统为Ctrl+D)结束输入。

5.2.5 Scanner 类的注意事项

(1)next () 与 nextLine () 的区别
  • next():以空白符(空格、制表符、回车符)为分隔符,仅读取空白
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Yvonne爱编码

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值