
📚所属栏目:java

前言
Java 运算符是实现数据运算、逻辑判断的核心工具,流程控制则是掌控程序执行顺序的关键,两者共同构成了 Java 程序的执行逻辑基础。本文将系统拆解 Java 全类型运算符的用法、优先级,以及分支、循环语句的实战场景,结合大量代码示例,帮助读者熟练掌握程序逻辑的构建方式。
一、Java 运算符全解析
运算符是用于对数据进行运算或逻辑判断的符号,Java 中的运算符按功能可分为算术运算符、关系运算符、逻辑运算符、赋值运算符、三元运算符等,每种运算符都有明确的语法规则和使用场景。
1.1 算术运算符:实现数值运算
算术运算符用于对数值类型数据进行加减乘除等运算,分为基本算术运算符和扩展算术运算符两类。
(1)基本算术运算符
包含+(加)、-(减)、*(乘)、/(除)、%(取模 / 取余),是最基础的数值运算工具。
public class ArithmeticBasicDemo {
public static void main(String[] args) {
int a = 10;
int b = 3;
// 加法运算
int addResult = a + b;
System.out.println("a + b = " + addResult); // 输出13
// 减法运算
int subResult = a - b;
System.out.println("a - b = " + subResult); // 输出7
// 乘法运算
int mulResult = a * b;
System.out.println("a * b = " + mulResult); // 输出30
// 除法运算:整数相除结果为整数,舍弃小数部分
int divResult1 = a / b;
System.out.println("a / b(整数相除) = " + divResult1); // 输出3
// 除法运算:浮点数相除结果为浮点数
double divResult2 = (double) a / b;
System.out.println("a / b(浮点数相除) = " + divResult2); // 输出3.3333333333333335
// 取模运算:返回除法的余数,符号与被除数一致
int modResult1 = a % b;
System.out.println("a % b = " + modResult1); // 输出1
int modResult2 = -10 % 3;
System.out.println("-10 % 3 = " + modResult2); // 输出-1
int modResult3 = 10 % -3;
System.out.println("10 % -3 = " + modResult3); // 输出1
}
}
注意事项:
- 整数相除时,结果会自动舍弃小数部分,如需保留小数,需将其中一个操作数转为浮点类型。
- 取模运算的结果符号与被除数一致,常用于判断奇偶性(
num % 2 == 0表示偶数)、循环取余等场景。 - 除数不能为 0,否则会抛出
ArithmeticException异常。
(2)扩展算术运算符
包含++(自增)、--(自减),用于实现变量值的自增 1 或自减 1,分为前置运算和后置运算两种形式。
public class ArithmeticExtendDemo {
public static void main(String[] args) {
int x = 5;
int y = 5;
// 前置自增:先自增1,再参与其他运算
int preIncrement = ++x;
System.out.println("前置自增后x = " + x); // 输出6
System.out.println("前置自增结果 = " + preIncrement); // 输出6
// 后置自增:先参与其他运算,再自增1
int postIncrement = y++;
System.out.println("后置自增后y = " + y); // 输出6
System.out.println("后置自增结果 = " + postIncrement); // 输出5
int m = 3;
int n = 3;
// 前置自减:先自减1,再参与其他运算
int preDecrement = --m;
System.out.println("前置自减后m = " + m); // 输出2
System.out.println("前置自减结果 = " + preDecrement); // 输出2
// 后置自减:先参与其他运算,再自减1
int postDecrement = n--;
System.out.println("后置自减后n = " + n); // 输出2
System.out.println("后置自减结果 = " + postDecrement); // 输出3
}
}
注意事项:
- 自增 / 自减运算符只能作用于变量,不能作用于常量(如
5++会编译报错)。 - 在复杂表达式中,需注意前置和后置运算的区别,避免逻辑错误。
1.2 关系运算符:实现条件判断
关系运算符用于判断两个数据之间的大小、相等关系,返回值为boolean类型(true或false),常用于分支语句和循环语句的条件判断。
Java 中的关系运算符包括:>(大于)、<(小于)、>=(大于等于)、<=(小于等于)、==(等于)、!=(不等于)。
public class RelationalOperatorDemo {
public static void main(String[] args) {
int a = 10;
int b = 20;
String s1 = "Java";
String s2 = "Java";
String s3 = new String("Java");
// 数值类型的关系判断
System.out.println("a > b : " + (a > b)); // 输出false
System.out.println("a < b : " + (a < b)); // 输出true
System.out.println("a >= 10 : " + (a >= 10)); // 输出true
System.out.println("b <= 19 : " + (b <= 19)); // 输出false
System.out.println("a == 10 : " + (a == 10)); // 输出true
System.out.println("a != b : " + (a != b)); // 输出true
// 引用类型的关系判断:== 比较的是对象地址,equals() 比较的是内容
System.out.println("s1 == s2 : " + (s1 == s2)); // 输出true(字符串常量池,地址相同)
System.out.println("s1 == s3 : " + (s1 == s3)); // 输出false(堆内存中不同对象,地址不同)
System.out.println("s1.equals(s3) : " + s1.equals(s3)); // 输出true(内容相同)
}
}
注意事项:
- 关系运算符的结果必须是
boolean类型,不能直接用于赋值(如int c = a > b;会编译报错)。 - 对于引用数据类型,
==比较的是对象的内存地址,equals()方法(默认也是比较地址,String 类重写后比较内容)用于比较对象的内容。 - 避免将浮点数用
==比较是否相等,由于精度丢失问题,建议通过判断两者差值的绝对值是否小于某个极小值(如1e-6)来判断。
1.3 逻辑运算符:实现复杂条件判断
逻辑运算符用于对多个boolean类型的值进行逻辑运算,返回值仍为boolean类型,常用于组合多个关系判断条件。
Java 中的逻辑运算符包括:&&(短路与)、||(短路或)、!(非)、&(逻辑与)、|(逻辑或)。
(1)短路逻辑运算符(常用)
&&(短路与):只有所有条件都为true时,结果才为true;如果第一个条件为false,则直接返回false,不再判断后续条件(短路特性)。||(短路或):只要有一个条件为true,结果就为true;如果第一个条件为true,则直接返回true,不再判断后续条件(短路特性)。
(2)非短路逻辑运算符
&(逻辑与):无论第一个条件是否为false,都会判断所有条件,最终返回所有条件的与结果。|(逻辑或):无论第一个条件是否为true,都会判断所有条件,最终返回所有条件的或结果。
(3)逻辑非运算符
-
!(非):对boolean值取反,!true返回false,!false返回true。public class LogicalOperatorDemo {
public static void main(String[] args) {
int num = 15;// 短路与:num > 10 为true,继续判断num < 20,最终为true boolean shortAnd = (num > 10) && (num < 20); System.out.println("短路与结果:" + shortAnd); // 输出true // 短路与:num < 10 为false,直接返回false,不执行num++ int temp1 = num; boolean shortAnd2 = (temp1 < 10) && (temp1++ > 0); System.out.println("短路与2结果:" + shortAnd2); // 输出false System.out.println("temp1的值:" + temp1); // 输出15(temp1++未执行) // 逻辑与:temp1 < 10 为false,仍会执行temp1++ int temp2 = num; boolean logicAnd = (temp2 < 10) & (temp2++ > 0); System.out.println("逻辑与结果:" + logicAnd); // 输出false System.out.println("temp2的值:" + temp2); // 输出16(temp2++已执行) // 短路或:num > 10 为true,直接返回true,不执行num-- int temp3 = num; boolean shortOr = (temp3 > 10) || (temp3-- < 0); System.out.println("短路或结果:" + shortOr); // 输出true System.out.println("temp3的值:" + temp3); // 输出15(temp3--未执行) // 逻辑或:num > 10 为true,仍会执行num-- int temp4 = num; boolean logicOr = (temp4 > 10) | (temp4-- < 0); System.out.println("逻辑或结果:" + logicOr); // 输出true System.out.println("temp4的值:" + temp4); // 输出14(temp4--已执行) // 逻辑非 boolean flag = true; boolean notFlag = !flag; System.out.println("!true = " + notFlag); // 输出false System.out.println("!false = " + !notFlag); // 输出true // 复杂逻辑组合 boolean complexCondition = (num > 0) && (num % 2 == 1) || (num == 0); System.out.println("复杂条件结果:" + complexCondition); // 输出true(15>0且是奇数) }}
注意事项:
- 短路逻辑运算符(
&&、||)由于具有短路特性,能提高程序执行效率,实际开发中优先使用。 - 逻辑运算符的操作数必须是
boolean类型,不能是其他类型(如1 && 2会编译报错)。
1.4 赋值运算符:实现变量赋值
赋值运算符用于将右侧的值赋值给左侧的变量,分为基本赋值运算符和复合赋值运算符两类。
(1)基本赋值运算符
=(赋值):将右侧的值(或表达式结果)赋值给左侧的变量,左侧必须是变量,不能是常量或表达式。
int a = 10; // 基本赋值
String name = "Java语法"; // 基本赋值
a = a + 5; // 将a+5的结果赋值给a
(2)复合赋值运算符
复合赋值运算符是赋值运算符与算术运算符的结合,用于简化代码,包括+=、-=、*=、/=、%=等。
语法格式:变量 复合赋值运算符 表达式,等价于变量 = 变量 算术运算符 表达式。
public class AssignmentOperatorDemo {
public static void main(String[] args) {
int a = 10;
// += 等价于 a = a + 5
a += 5;
System.out.println("a += 5 后:" + a); // 输出15
// -= 等价于 a = a - 3
a -= 3;
System.out.println("a -= 3 后:" + a); // 输出12
// *= 等价于 a = a * 2
a *= 2;
System.out.println("a *= 2 后:" + a); // 输出24
// /= 等价于 a = a / 4
a /= 4;
System.out.println("a /= 4 后:" + a); // 输出6
// %= 等价于 a = a % 4
a %= 4;
System.out.println("a %= 4 后:" + a); // 输出2
// 复合赋值运算符会自动进行类型转换
byte b = 5;
b += 3; // 等价于 b = (byte)(b + 3),自动强制类型转换
System.out.println("byte类型b += 3 后:" + b); // 输出8
// 以下代码编译报错:直接赋值不会自动类型转换
// byte c = 5;
// c = c + 3; // 错误:int类型无法赋值给byte类型
}
}
注意事项:
- 复合赋值运算符会自动进行强制类型转换,而直接使用算术运算符 + 赋值的形式不会,这是两者的核心区别。
- 赋值运算符的优先级较低,会先执行右侧的表达式,再将结果赋值给左侧变量。
1.5 三元运算符:简化分支判断
三元运算符(又称三目运算符)是 Java 中唯一的三目运算符,用于简化简单的if-else分支判断,返回一个具体的值。
语法格式:条件表达式 ? 表达式1 : 表达式2
-
执行逻辑:如果条件表达式为
true,则执行表达式 1 并返回其结果;如果为false,则执行表达式 2 并返回其结果。 -
要求:表达式 1 和表达式 2 的类型必须一致(或可以自动类型转换)。
public class TernaryOperatorDemo {
public static void main(String[] args) {
int score = 85;
int num1 = 20;
int num2 = 30;// 判断成绩等级 String grade = score >= 90 ? "优秀" : (score >= 80 ? "良好" : (score >= 60 ? "及格" : "不及格")); System.out.println("成绩等级:" + grade); // 输出良好 // 获取两个数的最大值 int maxNum = num1 > num2 ? num1 : num2; System.out.println("最大值:" + maxNum); // 输出30 // 获取三个数的最小值 int num3 = 15; int minNum = (num1 < num2 ? num1 : num2) < num3 ? (num1 < num2 ? num1 : num2) : num3; System.out.println("最小值:" + minNum); // 输出15 // 自动类型转换:表达式1和表达式2类型不同,自动转为范围更大的类型 double result = num1 > 25 ? 10 : 3.14; System.out.println("自动类型转换结果:" + result); // 输出3.14 }}
注意事项:
- 三元运算符适用于简单的二分支判断,复杂的多分支判断建议使用
if-else或switch语句,避免代码可读性降低。 - 三元运算符的结果必须被使用(如赋值给变量、作为参数传递),不能单独作为一条语句(如
score >= 60 ? "及格" : "不及格";会编译报错)。
1.6 运算符的优先级与结合性
当一个表达式中包含多个运算符时,会按照 "优先级从高到低" 的顺序执行;当优先级相同时,会按照 "结合性"(从左到右或从右到左)执行。
(1)优先级排序(从高到低,核心常用)
- 括号
() - 自增 / 自减
++、-- - 算术运算符
*、/、%>+、- - 关系运算符
>、<、>=、<=>==、!= - 逻辑运算符
&&>|| - 三元运算符
? : - 赋值运算符
=、+=、-=等
(2)结合性
-
大部分运算符的结合性是 "从左到右"(如算术运算符、关系运算符)。
-
赋值运算符、三元运算符的结合性是 "从右到左"(如
a = b = c;等价于a = (b = c);)。public class OperatorPriorityDemo {
public static void main(String[] args) {
int a = 2;
int b = 3;
int c = 4;// 优先级:括号 > 乘除 > 加减 int result1 = a + b * c; System.out.println("a + b * c = " + result1); // 输出14(先算3*4=12,再算2+12=14) int result2 = (a + b) * c; System.out.println("(a + b) * c = " + result2); // 输出20(先算2+3=5,再算5*4=20) // 优先级:自增 > 算术运算 > 关系运算 > 逻辑运算 int x = 5; boolean result3 = x++ > 5 && x < 8; System.out.println("x++ > 5 && x < 8 = " + result3); // 输出false(x++=5,5>5为false,短路与直接返回false) System.out.println("x的值:" + x); // 输出6 // 结合性:赋值运算符从右到左 int m = 1; int n = 2; int p = 3; m = n = p; // 等价于m = (n = p) System.out.println("m = " + m + ", n = " + n + ", p = " + p); // 输出m=3, n=3, p=3 // 结合性:算术运算符从左到右 int result4 = a + b + c; System.out.println("a + b + c = " + result4); // 输出9(先算2+3=5,再算5+4=9) }}
注意事项:
- 实际开发中,无需死记硬背运算符优先级,通过添加括号
()可以明确执行顺序,提高代码可读性。
1.7 强制类型转换的常见场景与问题
在数据类型转换中,强制类型转换是将大范围类型转为小范围类型的手动操作,容易出现数据溢出或精度丢失问题,以下是典型示例:
public class ForceTypeConvertDemo {
public static void main(String[] args) {
// int → byte(强制转换,可能溢出)
int a = 200;
byte b = (byte) a;
System.out.println(b); // 输出-56(200超出byte的取值范围,发生溢出)
// double → int(强制转换,精度丢失)
double d = 3.99;
int num = (int) d;
System.out.println(num); // 输出3(小数部分被舍弃,不是四舍五入)
// long → int(强制转换,可能溢出)
long l = 10000000000L;
int i = (int) l;
System.out.println(i); // 输出1410065408(超出int范围,溢出)
// 补充:浮点型转浮点型(精度丢失)
double bigDouble = 123456789.123456789;
float smallFloat = (float) bigDouble;
System.out.println(smallFloat); // 输出1.23456792E8(精度丢失,有效数字不足)
}
}
强制类型转换注意事项:
- 溢出原因:小范围类型的取值范围无法容纳大范围类型的值,导致数据按二进制补码循环存储(如 byte 的取值范围是 - 128~127,200 的二进制补码超出 1 字节,截断后得到 - 56)。
- 精度丢失:浮点型转整型时直接舍弃小数部分,浮点型之间转换时因有效数字不足导致精度下降,如需四舍五入,可使用
Math.round()方法(如Math.round(3.99)返回 4)。 - 安全转换:强制转换前应先判断值是否在目标类型的取值范围内,避免溢出(如
if (a >= Byte.MIN_VALUE && a <= Byte.MAX_VALUE) { byte b = (byte) a; })。
二、Java 流程控制:掌控程序执行顺序
流程控制用于决定程序的执行路径,分为分支结构(选择结构)和循环结构两类,分支结构根据条件判断执行不同代码块,循环结构根据条件重复执行某段代码。
2.1 分支结构:if-else 语句
if-else语句是最常用的分支结构,根据条件的真假执行不同的代码块,分为单分支、双分支和多分支三种形式。
(1)单分支 if 语句
语法格式:
if (条件表达式) {
// 条件为true时执行的代码块
}
执行逻辑:条件表达式为true时,执行大括号内的代码块;为false时,跳过代码块,继续执行后续代码。
public class IfSingleDemo {
public static void main(String[] args) {
int age = 18;
// 单分支判断:是否成年
if (age >= 18) {
System.out.println("你已成年,具备完全民事行为能力。");
}
int score = 95;
if (score >= 90) {
System.out.println("恭喜你,成绩达到优秀等级!");
System.out.println("获得奖学金奖励。");
}
System.out.println("单分支判断结束。");
}
}
注意事项:如果代码块只有一条语句,大括号{}可以省略,但建议始终保留,提高代码可读性和可维护性。
(2)双分支 if-else 语句
语法格式:
if (条件表达式) {
// 条件为true时执行的代码块
} else {
// 条件为false时执行的代码块
}
执行逻辑:条件表达式为true时执行 if 代码块,为false时执行 else 代码块,两者互斥,必有一个执行。
public class IfElseDemo {
public static void main(String[] args) {
int num = -7;
// 双分支判断:正数/非正数
if (num > 0) {
System.out.println(num + " 是正数。");
} else {
System.out.println(num + " 是负数或零。");
}
String gender = "女";
if (gender.equals("男")) {
System.out.println("性别:男");
} else {
System.out.println("性别:女");
}
}
}
(3)多分支 if-else if-else 语句
语法格式:
if (条件表达式1) {
// 条件1为true时执行的代码块
} else if (条件表达式2) {
// 条件1为false、条件2为true时执行的代码块
} else if (条件表达式3) {
// 条件1、2为false、条件3为true时执行的代码块
} else {
// 所有条件都为false时执行的代码块
}
执行逻辑:从上到下依次判断条件表达式,只要有一个条件为true,就执行对应的代码块,后续条件不再判断;如果所有条件都为false,则执行 else 代码块。
public class IfElseIfDemo {
public static void main(String[] args) {
int score = 75;
String grade;
// 多分支判断成绩等级
if (score >= 90 && score <= 100) {
grade = "优秀";
} else if (score >= 80 && score < 90) {
grade = "良好";
} else if (score >= 70 && score < 80) {
grade = "中等";
} else if (score >= 60 && score < 70) {
grade = "及格";
} else if (score >= 0 && score < 60) {
grade = "不及格";
} else {
grade = "无效成绩";
}
System.out.println("你的成绩等级是:" + grade); // 输出中等
// 多分支判断季节
int month = 10;
if (month >= 3 && month <= 5) {
System.out.println(month + "月属于春季。");
} else if (month >= 6 && month <= 8) {
System.out.println(month + "月属于夏季。");
} else if (month >= 9 && month <= 11) {
System.out.println(month + "月属于秋季。");
} else if (month == 12 || month >= 1 && month <= 2) {
System.out.println(month + "月属于冬季。");
} else {
System.out.println(month + "月是无效月份。");
}
}
}
注意事项:
- 多分支的条件表达式之间应避免重叠,确保逻辑严谨。
- else 代码块是可选的,如果不需要处理所有条件为 false 的情况,可以省略 else。
2.2 分支结构:switch 语句
switch语句是另一种分支结构,适用于对一个变量的多个固定值进行判断,语法简洁,可读性高。
(1)switch 语句基本语法
switch (表达式) {
case 常量值1:
// 表达式等于常量值1时执行的代码块
break; // 跳出switch语句
case 常量值2:
// 表达式等于常量值2时执行的代码块
break;
// 更多case语句
default:
// 表达式不等于任何常量值时执行的代码块
break;
}
核心要求:
-
表达式的类型只能是:byte、short、int、char(及其包装类)、String(JDK7 + 支持)、枚举(Enum)。
-
case 后的常量值必须唯一,且类型与表达式类型一致。
-
break 语句用于跳出 switch 语句,避免执行后续 case 代码块(穿透现象)。
-
default 语句是可选的,用于处理所有 case 不匹配的情况,位置可灵活放置(通常放在最后)。
public class SwitchBasicDemo {
public static void main(String[] args) {
// 整数类型的switch判断
int week = 3;
String weekName;
switch (week) {
case 1:
weekName = "星期一";
break;
case 2:
weekName = "星期二";
break;
case 3:
weekName = "星期三";
break;
case 4:
weekName = "星期四";
break;
case 5:
weekName = "星期五";
break;
case 6:
weekName = "星期六";
break;
case 7:
weekName = "星期日";
break;
default:
weekName = "无效的星期数";
break;
}
System.out.println("今天是:" + weekName); // 输出星期三// 字符串类型的switch判断(JDK7+) 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; } }}
(2)switch 语句的穿透现象
如果 case 语句后没有添加 break 语句,会发生 "穿透现象",即执行完当前 case 的代码块后,会继续执行后续 case 的代码块,直到遇到 break 或 switch 语句结束。
穿透现象可用于处理多个 case 需要执行相同代码的场景,简化代码。
public class SwitchPenetrationDemo {
public static void main(String[] args) {
// 利用穿透现象判断工作日/休息日
int week = 6;
switch (week) {
case 1:
case 2:
case 3:
case 4:
case 5:
System.out.println(week + "是工作日,需要上班。");
break;
case 6:
case 7:
System.out.println(week + "是休息日,可以休息。");
break;
default:
System.out.println("无效的星期数。");
break;
}
// 未添加break的穿透现象(慎用)
int num = 2;
switch (num) {
case 1:
System.out.println("执行case 1");
case 2:
System.out.println("执行case 2");
case 3:
System.out.println("执行case 3");
default:
System.out.println("执行default");
}
// 输出:执行case 2、执行case 3、执行default(穿透执行)
}
}
(3)switch 语句与 if-else 语句的对比
| 对比维度 | switch 语句 | if-else 语句 |
|---|---|---|
| 适用场景 | 变量的多个固定值判断 | 复杂的条件判断(范围、逻辑组合等) |
| 可读性 | 变量多值判断时可读性更高 | 简单条件判断时可读性高,复杂条件稍差 |
| 执行效率 | 底层采用查找表 / 跳转表,效率较高 | 依次判断条件,效率与条件顺序相关 |
| 支持类型 | 有限类型(byte/short/int/char/String/ 枚举) | 支持所有 boolean 类型的条件表达式 |
2.3 循环结构:for 循环
for 循环是最常用的循环结构,适用于已知循环次数的场景,语法格式清晰,便于控制循环过程。
(1)for 循环基本语法
for (初始化表达式; 条件表达式; 更新表达式) {
// 循环体:条件表达式为true时重复执行的代码块
}
执行流程:
-
执行初始化表达式(仅执行一次),用于初始化循环变量。
-
判断条件表达式:
- 若为
true,执行循环体代码块; - 若为
false,跳出循环,结束 for 循环。
- 若为
-
执行更新表达式,更新循环变量的值。
-
回到步骤 2,重复执行,直到条件表达式为
false。public class ForBasicDemo {
public static void main(String[] args) {
// 示例1:循环输出1-5的数字
for (int i = 1; i <= 5; i++) {
System.out.println("i = " + i);
}// 示例2:计算1-100的累加和 int sum = 0; for (int num = 1; num <= 100; num++) { sum += num; } System.out.println("1-100的累加和:" + sum); // 输出5050 // 示例3:循环输出数组元素 int[] arr = {10, 20, 30, 40, 50}; for (int j = 0; j < arr.length; j++) { System.out.println("arr[" + j + "] = " + arr[j]); } // 示例4:倒序输出10-1的数字 for (int k = 10; k >= 1; k--) { System.out.println("k = " + k); } }}
(2)增强 for 循环(foreach 循环)
增强 for 循环(JDK5 + 支持)用于遍历数组或集合中的元素,无需关心循环索引,语法简洁,可读性高。
语法格式:
for (元素类型 变量名 : 数组/集合) {
// 循环体:变量名表示当前遍历到的元素
}
public class ForEachDemo {
public static void main(String[] args) {
// 遍历数组
int[] arr = {1, 3, 5, 7, 9};
System.out.println("数组元素:");
for (int element : arr) {
System.out.print(element + " ");
}
System.out.println(); // 输出1 3 5 7 9
// 遍历字符串数组
String[] names = {"张三", "李四", "王五", "赵六"};
System.out.println("姓名列表:");
for (String name : names) {
System.out.println(name);
}
// 增强for循环的限制:无法修改数组元素的值(仅获取元素)
for (int num : arr) {
num *= 2; // 仅修改局部变量num,不会改变数组原元素
}
System.out.println("修改后数组元素:");
for (int element : arr) {
System.out.print(element + " ");
} // 仍输出1 3 5 7 9
}
}
注意事项:
- 增强 for 循环只能用于遍历,无法获取数组索引,也无法修改数组元素的原值(基本数据类型)。
- 遍历集合时,若在循环中修改集合(添加 / 删除元素),会抛出
ConcurrentModificationException异常。
(3)for 循环的特殊形式
-
初始化表达式可以声明多个同类型的循环变量,用逗号分隔。
-
更新表达式可以同时更新多个循环变量,用逗号分隔。
-
初始化表达式、条件表达式、更新表达式都可以省略(但分号不能省略),省略条件表达式表示无限循环。
public class ForSpecialDemo {
public static void main(String[] args) {
// 多个循环变量的for循环
for (int i = 0, j = 10; i <= 10 && j >= 0; i++, j--) {
System.out.println("i = " + i + ", j = " + j);
}// 省略初始化表达式(循环变量已提前声明) int k = 1; for (; k <= 5; k++) { System.out.println("k = " + k); } // 省略更新表达式(在循环体内更新) int m = 1; for (; m <= 5; ) { System.out.println("m = " + m); m++; // 手动更新循环变量 } // 无限循环(需在循环体内添加退出条件) int n = 1; for (;;) { System.out.println("无限循环:n = " + n); n++; if (n > 3) { break; // 退出无限循环 } } }}
2.4 循环结构:while 循环
while 循环适用于未知循环次数的场景,仅通过条件表达式控制循环的开始和结束。
(1)while 循环基本语法
初始化表达式;
while (条件表达式) {
// 循环体
更新表达式;
}
执行流程:
-
执行初始化表达式(仅执行一次)。
-
判断条件表达式:
- 若为
true,执行循环体和更新表达式; - 若为
false,跳出循环,结束 while 循环。
- 若为
-
回到步骤 2,重复执行,直到条件表达式为
false。public class WhileBasicDemo {
public static void main(String[] args) {
// 示例1:循环输出1-5的数字
int i = 1;
while (i <= 5) {
System.out.println("i = " + i);
i++; // 更新循环变量
}// 示例2:计算1-100的偶数和 int sumEven = 0; int num = 1; while (num <= 100) { if (num % 2 == 0) { sumEven += num; } num++; } System.out.println("1-100的偶数和:" + sumEven); // 输出2550 // 示例3:未知次数循环(猜数字游戏) int randomNum = (int) (Math.random() * 100) + 1; // 生成1-100的随机数 int guessNum = 0; java.util.Scanner scanner = new java.util.Scanner(System.in); while (guessNum != randomNum) { System.out.print("请输入你猜测的数字(1-100):"); guessNum = scanner.nextInt(); if (guessNum > randomNum) { System.out.println("猜大了,请继续猜测!"); } else if (guessNum < randomNum) { System.out.println("猜小了,请继续猜测!"); } else { System.out.println("恭喜你,猜对了!"); } } scanner.close(); }}
注意事项:
- 必须在循环体内添加更新表达式,否则循环变量不会改变,会导致无限循环。
- 条件表达式的结果必须是
boolean类型,不能是其他类型。
2.5 循环结构:do-while 循环
do-while 循环是 while 循环的变种,特点是 "先执行,后判断",无论条件是否满足,循环体至少执行一次。
(1)do-while 循环基本语法
初始化表达式;
do {
// 循环体
更新表达式;
} while (条件表达式);
执行流程:
-
执行初始化表达式(仅执行一次)。
-
执行循环体和更新表达式(至少执行一次)。
-
判断条件表达式:
- 若为
true,回到步骤 2,继续循环; - 若为
false,跳出循环,结束 do-while 循环。
public class DoWhileDemo {
public static void main(String[] args) {
// 示例1:循环输出1-5的数字
int i = 1;
do {
System.out.println("i = " + i);
i++;
} while (i <= 5);// 示例2:条件不满足时,循环体仍执行一次 int j = 6; do { System.out.println("j = " + j); // 会输出j=6 j++; } while (j <= 5); // 示例3:用户输入验证(确保至少输入一次) java.util.Scanner scanner = new java.util.Scanner(System.in); String password; do { System.out.print("请输入密码(6位数字):"); password = scanner.next(); } while (password.length() != 6 || !password.matches("\\d+")); System.out.println("密码输入格式正确!"); scanner.close(); }}
- 若为
(2)while 循环与 do-while 循环的对比
| 对比维度 | while 循环 | do-while 循环 |
|---|---|---|
| 执行顺序 | 先判断,后执行 | 先执行,后判断 |
| 循环体执行次数 | 可能为 0 次(条件初始为 false) | 至少 1 次 |
| 适用场景 | 未知循环次数,可能不执行 | 未知循环次数,必须执行一次 |
2.6 循环控制语句:break 与 continue
break和continue语句用于灵活控制循环的执行流程,break用于跳出循环,continue用于跳过当前循环的剩余部分,进入下一次循环。
(1)break 语句
break语句有两种用法:
-
跳出单层循环:在循环体内使用
break,直接跳出当前循环,结束循环执行。 -
跳出多层循环:通过标签(label)标记外层循环,在内层循环中使用
break 标签名,跳出标记的外层循环。public class BreakDemo {
public static void main(String[] args) {
// 跳出单层for循环
for (int i = 1; i <= 10; i++) {
if (i == 6) {
break; // 当i=6时,跳出循环
}
System.out.println("i = " + i); // 输出1-5
}// 跳出单层while循环 int j = 1; while (j <= 10) { if (j == 6) { break; } System.out.println("j = " + j); // 输出1-5 j++; } // 跳出多层循环(使用标签) outer: // 外层循环标签 for (int m = 1; m <= 3; m++) { inner: // 内层循环标签 for (int n = 1; n <= 3; n++) { if (m == 2 && n == 2) { break outer; // 跳出外层循环 } System.out.println("m = " + m + ", n = " + n); } } // 输出:m=1,n=1; m=1,n=2; m=1,n=3; m=2,n=1 }}
(2)continue 语句
continue语句有两种用法:
-
跳过当前单层循环:在循环体内使用
continue,跳过当前循环的剩余代码,直接进入下一次循环。 -
跳过当前多层循环的内层:通过标签标记外层循环,使用
continue 标签名,跳过内层循环,直接进入外层循环的下一次迭代。public class ContinueDemo {
public static void main(String[] args) {
// 跳过当前for循环(输出1-10的奇数)
for (int i = 1; i <= 10; i++) {
if (i % 2 == 0) {
continue; // 跳过偶数,直接进入下一次循环
}
System.out.println("奇数:" + i); // 输出1、3、5、7、9
}// 跳过当前while循环 int j = 0; while (j < 10) { j++; if (j % 2 == 0) { continue; } System.out.println("奇数:" + j); // 输出1、3、5、7、9 } // 跳过内层循环(使用标签) outer: for (int m = 1; m <= 3; m++) { for (int n = 1; n <= 3; n++) { if (n == 2) { continue outer; // 跳过内层循环剩余部分,进入外层循环下一次迭代 } System.out.println("m = " + m + ", n = " + n); } } // 输出:m=1,n=1; m=2,n=1; m=3,n=1 }}
2.7 循环嵌套
循环嵌套是指在一个循环体内包含另一个完整的循环,外层循环控制循环的轮数,内层循环控制每轮的执行次数。常见的有 for-for 嵌套、for-while 嵌套等,适用于处理二维数据(如二维数组)、矩阵运算等场景。
public class LoopNestingDemo {
public static void main(String[] args) {
// 示例1:打印九九乘法表
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:打印矩形(5行8列*)
for (int row = 1; row <= 5; row++) {
for (int col = 1; col <= 8; col++) {
System.out.print("*");
}
System.out.println();
}
// 示例3:遍历二维数组
int[][] twoDArr = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
for (int i = 0; i < twoDArr.length; i++) {
for (int j = 0; j < twoDArr[i].length; j++) {
System.out.print(twoDArr[i][j] + " ");
}
System.out.println();
}
}
}
注意事项:
- 循环嵌套的层数不宜过多(通常不超过 3 层),否则会导致代码可读性下降和性能损耗。
- 外层循环和内层循环的循环变量不能重名,避免变量冲突。
三、总结
- 运算符是 Java 程序的运算基础,按功能可分为算术、关系、逻辑、赋值、三元运算符等,使用时需注意优先级、结合性,以及强制类型转换的溢出和精度丢失问题。
- 流程控制分为分支结构和循环结构,
if-else适用于复杂条件判断,switch适用于变量多固定值判断;for适用于已知循环次数,while/do-while适用于未知循环次数。 break用于跳出循环,continue用于跳过当前循环剩余部分,循环嵌套适用于处理二维数据等复杂场景,合理使用这些语句能灵活掌控程序执行逻辑。- 实际开发中,应根据业务场景选择合适的运算符和流程控制语句,注重代码的可读性和逻辑严谨性,避免无限循环、条件重叠等常见错误。