网站首页 > java教程 正文
本文将全面介绍Java中的流程控制结构,包括条件语句(if/else, switch)和循环结构(for, while, do-while),并提供丰富的示例代码和对比分析。
一、条件语句
结构 | 语法 | 适用场景 | 特点 |
if | if (条件) { ... } | 单一条件判断 | 最简单的条件结构 |
if-else | if (条件) { ... } else { ... } | 二选一条件 | 处理true/false两种情况 |
if-else if-else | if (条件1) { ... } else if (条件2) { ... } else { ... } | 多条件判断 | 依次检查多个条件 |
嵌套if | if (条件1) { if (条件2) { ... } } | 复杂条件逻辑 | 条件中包含子条件 |
switch | java switch (变量) { case 值1: ... break; default: ... } | 等值多分支 | 清晰的多路分支 |
switch表达式 (Java 12+) | java var result = switch (变量) { case 1 -> "A"; default -> "B"; }; | 多分支返回值 | 更简洁,直接返回结果 |
1. if语句
if语句是最基础的条件控制结构,根据布尔表达式的结果决定是否执行某段代码。
if (条件表达式) {
// 条件为true时执行的代码
}
示例:判断天气是否适合出门
boolean isSunny = true;
if (isSunny) {
System.out.println("今天天气晴朗,适合出门散步!");
}
2. if-else语句
当需要条件为false时执行另一段代码,可以使用if-else结构。
if (条件表达式) {
// 条件为true时执行的代码
} else {
// 条件为false时执行的代码
}
示例:判断用户年龄是否成年
int age = 17;
if (age >= 18) {
System.out.println("您已成年,可以观看此内容。");
} else {
System.out.println("您未成年,请家长陪同观看。");
}
3. if-else if-else多重条件
当有多个条件需要判断时,可以使用if-else if-else结构。
if (条件1) {
// 条件1为true时执行的代码
} else if (条件2) {
// 条件2为true时执行的代码
} else if (条件3) {
// 条件3为true时执行的代码
} else {
// 所有条件都为false时执行的代码
}
示例:考试成绩评级
int score = 85;
if (score >= 90) {
System.out.println("优秀!");
} else if (score >= 80) {
System.out.println("良好!");
} else if (score >= 60) {
System.out.println("及格");
} else {
System.out.println("不及格,需要努力!");
}
4. 嵌套if语句
if语句可以嵌套使用,实现更复杂的条件判断。
示例:判断年份是否为闰年
int year = 2024;
boolean isLeapYear = false;
if (year % 4 == 0) {
if (year % 100 != 0) {
isLeapYear = true;
} else {
if (year % 400 == 0) {
isLeapYear = true;
}
}
}
if (isLeapYear) {
System.out.println(year + "年是闰年");
} else {
System.out.println(year + "年不是闰年");
}
5. switch语句
switch语句用于多分支选择,比多重if-else更清晰。
switch (表达式) {
case 值1:
// 代码块1
break;
case 值2:
// 代码块2
break;
// 可以有任意数量的case语句
default:
// 默认代码块
}
示例:根据星期几安排活动
int dayOfWeek = 3;
String activity;
switch (dayOfWeek) {
case 1:
activity = "周一:团队会议";
break;
case 2:
activity = "周二:代码审查";
break;
case 3:
activity = "周三:学习新技术";
break;
case 4:
activity = "周四:项目开发";
break;
case 5:
activity = "周五:项目演示";
break;
case 6:
activity = "周六:休息";
break;
case 7:
activity = "周日:家庭日";
break;
default:
activity = "无效的星期";
}
System.out.println(activity);
Java 12+增强的switch表达式
Java 12引入了更简洁的switch表达式语法:
String dayType = switch (dayOfWeek) {
case 1, 2, 3, 4, 5 -> "工作日";
case 6, 7 -> "周末";
default -> "无效";
};
System.out.println("今天是" + dayType);
条件语句对比表
特性 | if-else | switch |
适用场景 | 范围判断、复杂条件 | 等值判断、多分支选择 |
可读性 | 简单条件时好,复杂条件时差 | 多分支时清晰 |
性能 | 条件多时可能较慢 | 使用跳转表,性能稳定 |
表达式类型 | 布尔表达式 | 整型、枚举、String(Java 7+) |
灵活性 | 高 | 较低 |
可维护性 | 条件多时较差 | 分支多时较好 |
二、循环结构
结构 | 语法 | 适用场景 | 特点 |
for | for (初始化; 条件; 步进) { ... } | 已知循环次数 | 控制变量在循环头定义 |
增强for | for (类型 变量 : 集合) { ... } | 遍历数组/集合 | 简洁,无需索引 |
while | while (条件) { ... } | 条件先验循环 | 可能一次都不执行 |
do-while | do { ... } while (条件); | 条件后验循环 | 至少执行一次 |
1. for循环
for循环是最常用的循环结构,适合已知循环次数的情况。
for (初始化; 条件; 更新) {
// 循环体
}
示例:打印乘法表
// 打印9x9乘法表
for (int i = 1; i <= 9; i++) {
for (int j = 1; j <= i; j++) {
System.out.print(j + "×" + i + "=" + (i * j) + "\t");
}
System.out.println(); // 换行
}
2. 增强for循环(foreach)
Java 5引入的增强for循环,用于遍历数组或集合。
for (元素类型 变量名 : 数组或集合) {
// 循环体
}
示例:遍历数组
String[] fruits = {"苹果", "香蕉", "橙子", "葡萄"};
for (String fruit : fruits) {
System.out.println("我喜欢吃" + fruit);
}
3. while循环
while循环在不确定循环次数,但知道循环条件时使用。
while (条件) {
// 循环体
}
示例:猜数字游戏
import java.util.Scanner;
import java.util.Random;
public class GuessNumber {
public static void main(String[] args) {
Random random = new Random();
int target = random.nextInt(100) + 1; // 1-100的随机数
int guess;
int attempts = 0;
Scanner scanner = new Scanner(System.in);
System.out.println("猜数字游戏开始!(1-100)");
while (true) {
System.out.print("请输入你的猜测:");
guess = scanner.nextInt();
attempts++;
if (guess < target) {
System.out.println("太小了!");
} else if (guess > target) {
System.out.println("太大了!");
} else {
System.out.println("恭喜你猜对了!用了" + attempts + "次。");
break;
}
}
scanner.close();
}
}
4. do-while循环
do-while循环先执行一次循环体,再判断条件,至少执行一次。
do {
// 循环体
} while (条件);
示例:用户菜单选择
import java.util.Scanner;
public class MenuSystem {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int choice;
do {
System.out.println("\n==== 菜单系统 ====");
System.out.println("1. 查看个人信息");
System.out.println("2. 修改密码");
System.out.println("3. 退出系统");
System.out.print("请选择(1-3): ");
choice = scanner.nextInt();
switch (choice) {
case 1:
System.out.println("显示个人信息...");
break;
case 2:
System.out.println("修改密码功能...");
break;
case 3:
System.out.println("感谢使用,再见!");
break;
default:
System.out.println("无效选择,请重新输入!");
}
} while (choice != 3);
scanner.close();
}
}
循环结构对比表
特性 | for循环 | while循环 | do-while循环 |
适用场景 | 已知循环次数 | 未知循环次数,但知道条件 | 至少执行一次,再检查条件 |
初始化 | 循环内部初始化 | 循环外部初始化 | 循环外部初始化 |
语法复杂度 | 中等 | 简单 | 中等 |
使用频率 | 高 | 中 | 低 |
可读性 | 循环次数明确时好 | 条件明确时好 | 需要至少执行一次时好 |
三、循环控制语句
语句 | 作用 | 适用场景 |
break | 退出当前循环 | 满足条件时提前终止 |
continue | 跳过本次迭代 | 跳过特定条件的处理 |
带标签break | 退出指定循环 | 多层循环中跳出外层 |
带标签continue | 继续指定循环 | 多层循环中继续外层 |
1. break语句
break用于立即退出当前循环或switch语句。
示例:查找数组中第一个负数
int[] numbers = {3, 5, -2, 7, -8, 4};
int firstNegative = 0;
for (int num : numbers) {
if (num < 0) {
firstNegative = num;
break; // 找到第一个负数就退出循环
}
}
System.out.println("第一个负数是:" + firstNegative);
2. continue语句
continue跳过当前循环的剩余部分,直接开始下一次循环。
示例:打印1-10的奇数
for (int i = 1; i <= 10; i++) {
if (i % 2 == 0) {
continue; // 跳过偶数
}
System.out.println("奇数:" + i);
}
3. 带标签的break和continue
Java支持标签,可以用于控制多层循环的跳出。
示例:矩阵中查找特定值
int[][] matrix = {
{1, 2, 3},
{4, 5, 6},
{7, 8, 9}
};
int target = 5;
boolean found = false;
outerLoop: // 标签
for (int i = 0; i < matrix.length; i++) {
for (int j = 0; j < matrix[i].length; j++) {
if (matrix[i][j] == target) {
found = true;
System.out.println("找到" + target + "在位置(" + i + "," + j + ")");
break outerLoop; // 跳出外层循环
}
}
}
if (!found) {
System.out.println("未找到" + target);
}
四、高级流程控制技巧
特性 | 版本 | 优点 |
String in switch | Java 7+ | 支持字符串比较 |
switch表达式 | Java 12+ | 可返回值,更简洁 |
yield返回值 | Java 13+ | switch中返回值 |
模式匹配instanceof | Java 16+ | 简化类型检查和转换 |
1. 使用Stream API进行流程控制(Java 8+)
Java 8引入的Stream API提供了更函数式的流程控制方式。
示例:过滤和遍历集合
import java.util.Arrays;
import java.util.List;
public class StreamExample {
public static void main(String[] args) {
List<String> languages = Arrays.asList("Java", "Python", "C++", "JavaScript", "Ruby");
// 使用Stream过滤并打印长度大于4的语言
languages.stream()
.filter(lang -> lang.length() > 4)
.forEach(System.out::println);
// 并行处理
languages.parallelStream()
.map(String::toUpperCase)
.forEachOrdered(System.out::println);
}
}
2. 使用Optional避免空指针检查(Java 8+)
Optional可以帮助减少if-else的空值检查。
import java.util.Optional;
public class OptionalExample {
public static void main(String[] args) {
String name = "Alice";
// String name = null;
Optional.ofNullable(name)
.ifPresentOrElse(
n -> System.out.println("Hello, " + n),
() -> System.out.println("Hello, Guest")
);
}
}
3. 模式匹配(Java 14+预览,16+正式)
Java 16引入了模式匹配的instanceof,简化了类型检查和转换。
public class PatternMatching {
public static void main(String[] args) {
Object obj = "Hello Java";
// 传统方式
if (obj instanceof String) {
String s = (String) obj;
System.out.println(s.toUpperCase());
}
// 模式匹配方式
if (obj instanceof String s) {
System.out.println(s.toUpperCase());
}
}
}
五、性能考虑与最佳实践
场景 | 推荐结构 | 原因 |
等值多分支 | switch | 可读性更好 |
范围判断 | if-else | switch不支持 |
集合遍历 | 增强for | 代码更简洁 |
需要索引 | 传统for | 可以访问索引 |
至少执行一次 | do-while | 保证执行 |
条件复杂 | if-else | 更灵活 |
1. 循环性能优化
- 减少循环内部的计算:将不依赖循环变量的计算移到循环外部
- 使用增强for循环:遍历集合时比传统for循环更高效
- 避免在循环中创建对象:特别是大量小对象
结构 | 性能考虑 | 优化建议 |
if-else | 将最可能为true的条件放前面 | 减少判断次数 |
switch | 使用跳转表,性能稳定 | 超过3个分支时优先使用 |
for | 避免在条件中调用方法 | 提前计算循环次数 |
while | 注意避免无限循环 | 确保条件会变为false |
嵌套循环 | 内层循环应尽量简单 | 减少总迭代次数 |
优化示例:
// 不推荐的写法
for (int i = 0; i < list.size(); i++) { // size()在每次迭代都调用
// ...
}
// 推荐的写法
int size = list.size(); // 提前计算
for (int i = 0; i < size; i++) {
// ...
}
// 最佳写法(遍历集合时)
for (String item : list) {
// ...
}
2. 条件语句最佳实践
- 将最可能为true的条件放在前面:提高条件判断效率
- 避免深层嵌套:超过3层的嵌套应考虑重构
- 使用卫语句(Guard Clauses):提前返回减少嵌套
卫语句示例:
// 传统嵌套写法
public void process(User user) {
if (user != null) {
if (user.isActive()) {
if (user.hasPermission()) {
// 核心逻辑
} else {
System.out.println("无权限");
}
} else {
System.out.println("用户未激活");
}
} else {
System.out.println("用户不存在");
}
}
// 使用卫语句改进
public void process(User user) {
if (user == null) {
System.out.println("用户不存在");
return;
}
if (!user.isActive()) {
System.out.println("用户未激活");
return;
}
if (!user.hasPermission()) {
System.out.println("无权限");
return;
}
// 核心逻辑
}
3. 选择适当的循环结构
场景 | 推荐循环结构 |
已知确切循环次数 | for循环 |
需要遍历数组或集合 | 增强for循环 |
循环次数未知,但有明确终止条件 | while循环 |
至少需要执行一次循环体 | do-while循环 |
需要并行处理集合元素 | parallelStream |
六、常见问题与解决方案
1. 无限循环问题
问题代码:
while (true) { // 缺少终止条件
System.out.println("无限循环...");
}
解决方案:
boolean running = true;
while (running) {
// 业务逻辑
if (exitCondition) {
running = false; // 或使用break
}
}
2. switch忘记break导致穿透
问题代码:
int day = 2;
switch (day) {
case 1: System.out.println("周一");
case 2: System.out.println("周二"); // 忘记break
case 3: System.out.println("周三");
}
// 输出:周二 周三
解决方案:
int day = 2;
switch (day) {
case 1:
System.out.println("周一");
break;
case 2:
System.out.println("周二");
break;
case 3:
System.out.println("周三");
break;
}
或者使用Java 12+的switch表达式避免此问题:
switch (day) {
case 1 -> System.out.println("周一");
case 2 -> System.out.println("周二");
case 3 -> System.out.println("周三");
}
3. 循环性能问题
问题代码:
for (int i = 0; i < expensiveOperation(); i++) { // 每次循环都调用
// ...
}
解决方案:
int count = expensiveOperation(); // 提前计算
for (int i = 0; i < count; i++) {
// ...
}
七、实际应用案例
1. 用户登录验证
import java.util.Scanner;
public class LoginSystem {
public static void main(String[] args) {
String correctUsername = "admin";
String correctPassword = "123456";
int attempts = 3;
Scanner scanner = new Scanner(System.in);
while (attempts > 0) {
System.out.print("用户名:");
String username = scanner.nextLine();
System.out.print("密码:");
String password = scanner.nextLine();
if (username.equals(correctUsername) {
if (password.equals(correctPassword)) {
System.out.println("登录成功!");
break;
} else {
attempts--;
System.out.println("密码错误!剩余尝试次数:" + attempts);
}
} else {
attempts--;
System.out.println("用户名不存在!剩余尝试次数:" + attempts);
}
}
if (attempts == 0) {
System.out.println("登录失败,账户已锁定!");
}
scanner.close();
}
}
2. 购物车结算系统
import java.util.HashMap;
import java.util.Map;
public class ShoppingCart {
public static void main(String[] args) {
Map<String, Double> products = new HashMap<>();
products.put("苹果", 5.5);
products.put("香蕉", 3.2);
products.put("牛奶", 8.0);
products.put("面包", 6.5);
Map<String, Integer> cart = new HashMap<>();
cart.put("苹果", 2);
cart.put("牛奶", 1);
cart.put("面包", 3);
double total = 0.0;
System.out.println("购物清单:");
System.out.println("商品\t单价\t数量\t小计");
for (Map.Entry<String, Integer> entry : cart.entrySet()) {
String product = entry.getKey();
int quantity = entry.getValue();
if (products.containsKey(product)) {
double price = products.get(product);
double subtotal = price * quantity;
total += subtotal;
System.out.printf("%s\t%.2f\t%d\t%.2f%n",
product, price, quantity, subtotal);
} else {
System.out.println("警告:商品" + product + "已下架");
}
}
System.out.printf("总计:%.2f%n", total);
// 根据总金额提供折扣
if (total > 100) {
System.out.println("符合满100减20优惠!");
total -= 20;
} else if (total > 50) {
System.out.println("符合满50减5优惠!");
total -= 5;
}
System.out.printf("实付金额:%.2f%n", total);
}
}
总结
Java流程控制是编程的基础,合理使用条件语句和循环结构可以:
- 使代码逻辑更清晰
- 提高代码执行效率
- 增强程序的可读性和可维护性
- 处理复杂的业务逻辑
记住以下关键点:
- 根据场景选择合适的流程控制结构
- 避免过度嵌套,保持代码扁平化
- 注意循环和条件的性能影响
- 利用Java新特性简化代码(如switch表达式、模式匹配)
- 遵循最佳实践,编写干净、高效的代码
Java 流程控制就是群 “代码戏精”!if傲娇守门,for循环永动,稍有不慎,程序秒变 “失控现场”!
猜你喜欢
- 2025-04-30 2025 及未来 RAG 趋势:深入解析四大创新技术
- 2025-04-30 AI 时代程序员生存指南:掌握这 3 个核心能力稳赢未来
- 2025-04-30 java好学吗?完全没经验能学会吗(java好学嘛)
- 2025-04-30 Java面试题: 项目开发中的有哪些成长?该如何回答
- 2025-04-30 Java17,有史以来最快 JDK(java 运行速度)
- 2025-04-30 深入解析Java虚拟机(JVM)底层原理
- 2025-04-30 京东大佬问我,java高级技术人员要掌握哪些技术呢?
- 2025-04-30 猎聘同道精英汇:嘉宾徐文伟分享分布式高并发Java架构
- 2025-04-30 猎聘同道精英汇:51信用卡王霖分享Java项目的技术选型
- 2025-04-30 JUnit5:Java单元测试框架的新宠儿
你 发表评论:
欢迎- 最近发表
-
- 多种负载均衡算法及其Java代码实现
- 输入www.baidu.com背后经历了啥?说清楚这个,已经超过90%的人了
- 优化MySQL:为什么你应该用 UNSIGNED INT 存储IP地址
- 实模式下CPU如何获取数据及指令(实模式寻址方式)
- java基础都在这了,小主们拿去吧(java基础是指什么)
- 盘点爬虫语言为何选择Python而不是Java
- 搭载Dubbo+Zookeeper踩了这么多坑,我终于决定写下这篇
- 网络协议之TCP/IP协议(面试必考内容) - javaEE初阶 - 细节狂魔
- 深夜报警!10亿次请求暴击,如何用Redis找出最热IP?
- VPN技术(IPsec/L2TP/SSLVPN/PPTP)学习笔记
- 标签列表
-
- java反编译工具 (77)
- java反射 (57)
- java接口 (61)
- java随机数 (63)
- java7下载 (59)
- java数据结构 (61)
- java 三目运算符 (65)
- java对象转map (63)
- Java继承 (69)
- java字符串替换 (60)
- 快速排序java (59)
- java并发编程 (58)
- java api文档 (60)
- centos安装java (57)
- java调用webservice接口 (61)
- java深拷贝 (61)
- 工厂模式java (59)
- java代理模式 (59)
- java.lang (57)
- java连接mysql数据库 (67)
- java重载 (68)
- java 循环语句 (66)
- java反序列化 (58)
- java时间函数 (60)
- java是值传递还是引用传递 (62)
本文暂时没有评论,来添加一个吧(●'◡'●)