目录
前言:Java虽然是面向对象语言,但是也有结构化语句,结构化语句有三种:顺序、选择、循环,本章将介绍结构化语句的基础语法以及使用事项、应用场景等。同时 ,还配合了一些练习帮助大家巩固语法的使用,最后还完成一个猜数字小游戏。
1.顺序结构
概述:顺序语句就是你在写Java代码的时候,那些一条一条的语句,他在执行的时候是顺着执行的。
System.out.println("hello world");//hello world
System.out.println("李华");//李华
System.out.println(1 + 2);//3
2.选择结构
概述:选择结构也叫做分支结构,他是在执行程序的时候会根据条件选择一条语句进行执行。
选择语句有两种:if语句和switch语句
2.1.if语句
语法格式1:
if(布尔表达式){
语句块;
}
语法格式2:
if(布尔表达式){
语句块1;
} else{
语句块2;
}
语法格式3:
if(布尔表达式){
语句块1;
} else if(布尔表达式){
语句块2;
} else{
语句块3;
}
/******************if语句基础语法**********************/
/*
* 结论:
* 语法格式1:
* if(布尔表达式){
* 语句块;
* }
*
* 语法格式2:
* if(布尔表达式){
* 语句块1;
* } else{
* 语句块2;
* }
*
* 语法格式3:
* if(布尔表达式){
* 语句块1;
* } else if(布尔表达式){
* 语句块2;
* } else{
* 语句块3;
* }
*
* 注1:条件只能是boolean表达式
* 注2:不管多么复杂的语句只会选择一条路走
* */
//语法格式1:
int age = 20;
if(age >= 18){//如果大于18
System.out.println("成年");//打印成年
}
//语法格式2:
if(age > 20){
System.out.println("学习");//学习
} else{
System.out.println("实习");
}
//语法格式3:
int score = 100;
if(score >= 90){
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("错误数据");
}
//结果:优秀
//结论:if语句也说明了无论有多少条路你最终只选择一条路走
if语句的注意事项:
1.括号中的表达式只能是boolean表达式(值为布尔类型的表达式 或者 是布尔值)
2.无论有多少条路只会选择一条执行
3.else
的匹配遵循 "就近原则",即 else
会与 最近的、尚未匹配 else
的 if
语句 配对。
3.1.else
总是匹配最近的 if
(如果没有 {}
明确范围)。
3.2.使用 {}
可以显式控制 else
的匹配,避免歧义。
3.3.建议:嵌套 if-else
时,建议始终使用 {}
,提高代码可读性并防止逻辑错误。
if语句的练习
/**************if相关练习********************/
//1. 判断一个数字是奇数还是偶数
int n = 13;
if(n % 2 == 0){
System.out.println(n + "是偶数");
}else{
System.out.println(n + "是奇数");
}
//2. 判断一个年份是否为闰年
int year = 2023;
if((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0) ){
System.out.println(year + "是闰年");
}else{
System.out.println(year + "不是闰年");
}
2.2.switch语句
基本语法:
switch(表达式){
case 常量值1:
//代码块
break;
case 常量值2:
//代码块
break;
case 常量值3:
//代码块
break;
...//可以有多个case
default:
//默认情况
break;
}
int day = 7;
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;
}
//结果为:星期日
switch语句的使用细节 :
1.switch语句中:switch括号中的表达式只能放这几种类型:int char byte short String 枚举。
不可以是float long double boolean和复杂表达式如:a<3
解释:
switch是再JVM层面通过跳转表实现的,你可以通俗的理解为他底层匹配你的分路是通过偏移量的方式来完成的,而偏移量肯定是偏向整型而且范围不要太大要好一些,因此int char byte short 枚举等恰恰符合这一点,对于String是因为比较常用所以在JAVA7加进去的底层是以hashCode实现的。
对于float double为什么不可以?
因为他们存在精度问题,无法精准匹配对应的分支
对于long为什么不可以?
因为他范围太大了不适合做为偏移量(跳转表)
对于boolean和复杂表达式(eg:a<3)为什么不可以 ?
因为他们返回值都是true/false,我们switch的设计初衷是多分支精准匹配,而你现在就两个值true/false,这个就变成了条件判断,你完全可以使用if-else实现的没必要多此一举,违背switch的初衷
2.switch后面的括号中可以放变量、表达式、函数调用,只要他们的返回值类型是int char byte short String 枚举即可。也可以放常量但是写死了并没有实际意义(不建议这样写)。
为什么可以放变量、表达式、函数调用?
因为你放这些就意味着只要类型匹配程序就在在运行时确定值,也就意味着
switch
能处理动态输入(如用户输入、计算结果等),这样就提高了灵活性。
为什么放常量通常没意义?
请看下图:
3.case的写法:case后面要跟一个空格,然后再写常量值,最后打一个冒号
4.case后面只能写常量值
为什么case后面只能写常量值呢?
因为编译器需要在编译时确定所有
case
的值,才能生成一个静态的跳转表,而只有常量才能在编译时确定。如果case
值是变量,跳转表就无法预先构建。
5.为了良好的编码规范需要每一个分支后面写上break,如果没有break会出现穿透现象。
break是用来跳出switch的,如果没有break程序将一直执行直到遇到下一个break或者遇到switch的花括号。
6. default和case的顺序可以任意位置,但是一般我们把default写在最后面
switch(num){
default://default可以写在任意位置
System.out.println("输入错误");
break;
case 1:
System.out.println("1");
break;
case 2:
System.out.println("1");
break;
case 7:
System.out.println("7");
break;
}
3.if和switch对比总结
特性 | IF语句 | SWITCH语句 |
---|---|---|
条件类型 | 任何布尔表达式 | 整型、枚举、String(Java 7+) |
比较方式 | 范围、复杂逻辑 | 等值比较 |
分支数量 | 少量分支更清晰 | 多分支更清晰 |
执行方式 | 顺序判断 | 跳转表(可能更高效) |
可读性 | 简单条件时好 | 多离散值匹配时好 |
if多用于范围比较
switch多用于等值比较
通常if最常用
4.循环结构
循环结构有三种:for 、while 、do while其中while和for最常用
4.1.while循环
语法格式:
while(布尔表达式){
语句块;
}
//打印1到10的数字
int num = 1;
while(num <= 10){
System.out.print(num + " ");
num++;
}
注意1:循环条件必须是布尔表达式
注意2:一个有效的循环包括三个表达式:
- 表达式1:初始化语句
- 表达式2:循环条件(while循环中必须有)
- 表达式3:更新表达式
如果省略表达式3 会进入死循环
int a = 1;
while(a < 10){
System.out.print(a + " ");
// a++;
}
//程序进入了死循环
总结:while通常使用在循环次数未知的情况下
4.2.for循环
基本语法:
for(初始化语句;布尔表达式;更新表达式){
语句块;
}
//打印1到10的数字
for(int i = 1;i <= 10;i++){
System.out.println(i);
}
执行逻辑:
//练习---for循环的几种写法
//练习:计算1-100的和
//1.通用的写法
int sum = 0;
for(int i = 1;i <= 100;i++){
sum += i;
}
System.out.println(sum);
//2.初始化语句写在外面
int sum1 = 0;
int i = 1;
for(;i <= 100;i++){
sum1 += i;
}
System.out.println(sum1);
//3.更新表达式写在循环体中
int sum2 = 0;
for(int j = 1;j <= 100;){
sum2+=j;
j++;
}
System.out.println(sum2);
总结:for循环通常使用在循环次数已知的情况,通常用于数组的遍历
4.3.do while循环
do while循环很少用,他的特点是执行一次再判断条件。
基本语法
do{
循环语句;
}while(循环条件);
int num = 1;
do {
System.out.println(num);
num++;
} while (num <= 10);
注意:
1. do while 循环最后的分号不要忘记
2. 一般 do while 很少用到, 更推荐使用 for 和 while.
4.4.break
注意:break只用于switch语句、循环语句和 带标签的代码块
break用于跳出循环。
break配合三大循环使用,他对三大循环的行为都是一致的,遇到break直接跳出循环。
NO.1.break和while使用
//求100-200之间的第一个3的倍数
int num = 100;
while(num <= 200){
if(num % 3 ==0){
System.out.println(num);
break;
}
num++;
}
//结果:102
解释如下:
NO.2.break与for和do while使用
System.out.println("========for实现========");
for(int i = 100;i <= 200; i++){
if(i % 3 ==0){
System.out.println(i);
break;
}
}
System.out.println("=======do whiel实现============");
int num1 = 100;
do{
if(num1 % 3 == 0){
System.out.println(num1);
break;
}
num1++;
} while(num1 <= 200);
4.5.continue
注意:continue只用于循环语句和带标签的代码块
跳过本次循环,到下一次循环。
continue配合三大循环使用,他对while和do while的循环一致,对for就有点不一样了,但是本质是一样的,注意我说本质是一样的将会在下面的解释中体现。
NO.1.continue和for使用:遇到continue直接跳到更新表达式,再执行循环条件。
//找出100-200之间的所有3的倍数
System.out.println("========for实现=========");
for (int i = 100;i <= 200;i++){
if(i % 3 !=0) {//如果你不是3的倍数我就不将你输出
continue;
}
System.out.print(i + " ");//如果你是3的倍数我就将你输出
}
NO.2.continue与while使用:遇到continue直接跳到循环条件(但是一般continue需要加上更新表达式)
请先观察以下代码:
//求出100-200之间的所有3的倍数
int i = 100;
while(i <= 200){
if(i % 3 != 0){//如果你不是3的倍数我就不将你输出
continue;
}
System.out.print(i + " ");//如果你是3的倍数我就将你输出
i++;
}
运行结果:直接卡死了,陷入死循环
分析原因:
改正后的代码如下:
//求出100-200之间的所有3的倍数
int i = 100;
while(i <= 200){
if(i % 3 != 0){//如果你不是3的倍数我就不将你输出
i++;
continue;
}
System.out.print(i + " ");//如果你是3的倍数我就将你输出
i++;
}
如代码所见,我们在continue前面加上了i++ 。
接下来将解释为什么我认为continue对while和do while的行为本质与continue对for的行为一致
那么经过解释你也应该明白了一般在while和do while中有continue那么需要在其之前加上更新表达式。
那么肯定有人问更新表达式加在continue后面可不可以?
答案:不可以。
NO.3.continue和do while使用
//找出100-200之间的所有3的倍数
int i = 100;
do{
if(i % 3 != 0){//如果你不是3的倍数我就不将你输出
i++;
continue;
}
System.out.print(i + " ");//如果你是3的倍数我就将你输出
i++;
} while(i <= 200);
他的行为和while是一致的,这里不做过多的解释。
5.三大循环的对比总结
循环类型 | 适用场景 | 执行顺序 | 典型用例 |
---|---|---|---|
for | 循环次数已知,需控制变量 | 先判断,后执行 | 遍历数组、固定次数操作 |
while | 循环次数未知,先检查条件 | 先判断,后执行 | 条件驱动(如输入验证、游戏) |
do-while | 至少执行一次,再检查条件 | 先执行,后判断 | 菜单、资源初始化、重试逻辑 |
明确循环次数 →
for
不确定次数但需先判断 →
while
必须执行一次且可能继续 →
do-while
6.输入和输出
6.1.输入
输入他涉及面向对象的内容,在这里你只需要按步骤写即可
第一步:import java.util.Scanner; // 需要导入 util 包(必须在第一行)
第二步:Scanner sc = new Scanner(System.in);
第三步:输入整数的语句int num = sc.nextInt();
练习
//使用 Scanner 读取字符串/整数/浮点数
Scanner sc = new Scanner(System.in);
//读取字符串
//sc.next()-->以空格结束
//sc.nextLine()-->读一行以回车结束
String userName = sc.nextLine();
//读入整数
int age = sc.nextInt();
//读入浮点数
double height = sc.nextDouble();
System.out.println("名字" + userName);
System.out.println("年龄" + age);
System.out.println("身高" + height);
//使用 Scanner 循环读取 N 个数字,并求取其平均值
Scanner sc = new Scanner(System.in);
int sum = 0;//存放数之和
int num = 0;//记录输入个数
/*
*解释为什么使用while和循环条件hasNext()
* 1)首先循环次数不确定因此使用while循环
* 2)由于循环读入N次他是不确定你到底输入几次的因此使用hasNect()
* hasNext()的原理:
* 他会配合sc.nextInt()进行用户交互等待用户输入
* 如果用户输入后回车他就进行检测如果有数据他就返回true
* 如果用户输入:ctrl+D ==》停止输入 hasNext()返回false然后退出循环
* 可以说如果循环输入次数未知:就使用while==》自然就使用hasNext()做条件
*/
while(sc.hasNext()){//用户是否有数据输入
int temp = sc.nextInt();//输入一个整数
sum += temp;//求和
num++;//输入的数增加
}
System.out.println("输入的数的个数:" + num);
System.out.println("平均值:" + 1.0*sum/num);
/*
* 测试用例:1 2 3 4 5
* 结果:
* 输入的数的个数: 5
* 平均值: 3.0
* */
6.2.输出
输出有两种
方式一:
System.out.println(msg); // 输出一个字符串, 带换行
System.out.print(msg); // 输出一个字符串, 不带换行
例子:
System.out.println("hello word");
System.out.print("hello ");
System.out.println("word");
//结果
hello word
hello word
方式二:
System.out.printf(format, msg); // 格式化输出
例子:
int x = 10;
System.out.printf("%d",x);//10
//和你学过的c语言一致。
格式化字符串
转换符 | 类型 | 举例 | 输出结果 |
---|---|---|---|
%d | 十进制整数 | ("%d", 100) | 100 |
%x | 十六进制整数 | ("%x", 100) | 64 |
%o | 八进制整数 | ("%o", 100) | 144 |
%f | 定点浮点数 | ("%f", 100f) | 100.000000 |
%e | 指数浮点数 | ("%e", 100f) | 1.000000e+02 |
%g | 通用浮点数 | ("%g", 100f) | 100.000 |
%a | 十六进制浮点数 | ("%a", 100) | 0x1.9p6 |
%s | 字符串 | ("%s", 100) | 100 |
%c | 字符 | ("%c", '1') | 1 |
%b | 布尔值 | ("%b", 100) | true |
%h | 散列码 | ("%h", 100) | 64 |
%% | 百分号 | ("%.2f%%", 2/7f) | 0.29% |
7.猜数字游戏
先看结果
失败案例:
成功案例:
代码:
import java.util.Random;
import java.util.Scanner;
class Test {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
Random random = new Random();//默认随机数种子是系统时间
int gameNum = random.nextInt(101);//随机产生一个1-100的数
System.out.println(gameNum);
int num = 10;//只能猜10次
while(num > 0){//如果你的游戏次数还大于0就可以继续玩
System.out.println("请输入你所要猜的数字(1-100):");
int temp = sc.nextInt();
if(temp >=1 && temp <=100){//如果你输入的数字合法就往下走
if(temp == gameNum){
System.out.println("恭喜你,猜对了");
break;//猜对了就结束游戏
}else if(temp < gameNum){
System.out.println("猜小了");
num--;
System.out.println("你还有" + num + "次机会");
}else{
System.out.println("猜大了");
num--;
System.out.println("你还有" + num + "次机会");
}
}else{
System.out.println("输入的数字不合法!!!请重新输入");
}
}
if(num > 0){
System.out.println("游戏胜利");//如果10次内完成就胜利
}else{
System.out.println("游戏失败");//如果10次机会用完了就失败
}
}
}