Java 流程控制概述
笔记里有很多地方声明类而有些地方没有, 是因为本来我觉得不声明类会显得代码块简洁一点, 但是实际上码完然后复制到文档编辑器里, 删掉类声明的话后面的缩进全乱套了...所以有些我勤快了给他简洁化了, 而有些我没有 (超级大懒货说是).
Scanner
获取用户输入的信息, 就像是 C 语的 "scanf".
基础语法: Scanner 扫描器 = new Scanner(System.in);
Tips: Ctrl + Alt + V 可以在 new 对象(); 后自动创建变量.
扫描一个字符串:next
import java.util.Scanner;//创建扫描器 scanner1 回车会自动引用.
public class Demo {
public static void main(String[] args) {
Scanner scanner1 = new Scanner(System.in);//创建一个扫描器对象.
if (scanner1.hasNext()) {//检测有没有输入字符, 不检测也可以. 这里是判断它 "有没有", 所以用 has.
String text = scanner1.next();//使用 next 方法接收.
System.out.println("复读姬: " + text);
}
scanner1.close();//IO流的要用完就关, 不关闭就会一直占用资源. 放在 if 循环外边.
}
}
试着运行一下:

可见, 输入了一大串中间带空格的字符串, 却只会打印空格前的内容.
结论:
-
读到有效字符后才可以结束输入;
-
会自动去掉有效字符前的空白;
-
只有输入有效字符后, 才把在后面输入的空白作为分隔符/结束符;
-
不能得到带空格的字符串.
扫描多个字符串: nextline
import java.util.Scanner;
public class Demo1 {
public static void main(String[] args) {
Scanner scanner1 = new Scanner(System.in);
if (scanner1.hasNextLine()) {
String text = scanner1.nextLine();//使用 nextLine 方法接收.
System.out.println("复读姬: " + text);
}
scanner1.close();
}
}
试运行:

这回能够把整个带空格的字符串打印出来了.
结论:
-
Enter 为结束符, 即 nextLine 会返回回车之前的所有字符;
-
可以获得空白.
扫描其他数值类型
若扫描 float 类型, 则用 nextFloat;
一次类推, 有 nextByte, nextShort, nextInt, nextLong, nextFloat, nextDouble, nextChar...
应用: 计算平均数和总数.
import java.util.Scanner;
public class Demo3 {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
double sum = 0;//输入的数字的总和, 因为数字可能时小数所以用 double.
int total = 0;//输入的数字的个数.
System.out.println("输入数字, 或按其他键以进行计算.");
while (scanner.hasNextDouble()) {//while 循环, 当 scanner 扫描到 double 以外的类型则会跳出循环.
double num = scanner.nextDouble();//最近扫描到的数字.
total++;//当输入一个数字, total 自己 +1.
sum = sum + num;//新的 sum = 旧的 sum + 新输入的数字.
System.out.println("你输入了第 " + total + " 个数据, 现在总数为 " + sum);
}
System.out.println("这些数的总数: " + sum);
System.out.println("这些数的平均数: " + sum / total);
scanner.close();
}
}
输出如下:

注: 第 11 行, 可以写 total++, ++total, total = ++total, 但不能写成 total = total++.
total++ 和 ++total 都是直接自增;
total = ++total 是先让后面的 total 自增, 然后让前面的 total 等于自增后的 total;
而 total = total++ 是让后面的 total 完成指令后再自增, 即先让前面的等于后面的, 然后再让后面的 total 自增, 但是前面的 total 已经得到了值 (=0), 后面的怎么变也没有用, 就使得 total 一直等于 0.
所以不要使用后面两种容易混淆的写法.
流程结构
顺序结构
Java 的基本结构, 从上到下.
普通而伟大,无需多言 §( ̄▽ ̄)§
选择结构
if 选择结构
if 单分支语句
语法:
if (boolean表达式){
语句块;
}
当值为 true, 则执行语句块, 否则跳过不执行.
语句块里只有一句, {} 可以省略不写 (但为了可读性最好写上).

if 双分支语句
语法:
if (boolean表达式){
语句块A;
}else {
语句块B;
}
值为 true 时执行 语句块A, 否则执行 语句块B.

if 多分支语句
语法:
if(boolean表达式A){
语句块A;
}else if(boolean表达式B){
语句块B;
}else if(boolean表达式C){
语句块C;
}else{
语句块N
}
众表达式中执行其中值为 true 的分支的语句块.
运行过程中有一个为 true, 后面的就不会执行.

应用: 成绩评判.
import java.util.Scanner;
public class Demo4 {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
double score = input.nextDouble();
if (score <= 100 && score >= 90) {
System.out.println("优.");
} else if (score < 90 && score >= 80) {
System.out.println("良.");
} else if (score < 80 && score >= 60) {
System.out.println("可.");
} else if (score < 60 && score >= 0) {
System.out.println("不可.");
} else{
System.out.println("成绩非法!");
}
}
}
嵌套 if
在 if 或 if...else 中嵌套使用 if 或 if...else. (条件里面再加条件)
if (条件1) {
if (条件2) {
代码块1
} else {
代码块2
}
} else {
代码块3
}
switch 选择结构
语法:
switch(表达式){
case 值1:
语句块1;
break;
case 值2:
语句块2;
break;
...
default:
语句块X;
}
根据 switch 表达式里的值, 与 case 里的值配对, 每一个 case 都是一个 "分支", 若配对成功则执行, 当无一分支可以配对, 则执行 default 的语句.
括号里填写变量, 和 if 不一样 (详见下面示例).
允许的变量类型: byte, short, char, int, String
break 用于打断执行, 不添加则会一直运行,直到遇见下一个 break 或者结构结束.
case 的顺序无所谓, 但后面不能声明范围 (范围可以使用 if).
default 的位置不固定,可以在前亦可以在后.
int condition = 3;
switch (condition) {
case 1://当 condition = 1
System.out.println("肯德基");
break;
case 2://当 condition = 2
System.out.println("麦当劳");
break;
case 3://当 condition = 3
System.out.println("塔斯汀");
break;
default://不符合要求时
System.out.println("糠咽菜");//呜呜呜呜呜我不要吃糠咽菜(;´д`)ゞ
}
if 和 switch 的区别
()中的表达式 |
表达式变量取值 | 表达式变量个数 | 表达式变量类型 | |
|---|---|---|---|---|
| if | 条件表达式 (boolean值) | 等值判断/取值范围 | 1 个或多个 | 无限制 |
| switch | 变量 | 等值判断 | 1 个 | byte, short, char, int, String |
循环结构
循环结构由这些部分构成:
| 名称 | 作用 |
|---|---|
| 初始化 | 定义循环体的变量 |
| 循环条件 | 循环体执行的条件 |
| 循环体 | 被反复执行的程序段 |
| 迭代 | 循环体变量自增 |
while 循环
适合已知循环次数的情况, 结构紧凑.
语法:
初始化;
while (循环条件){//循环条件: boolean表达式.
循环体;
}
当值为 true 时, 循环会一直进行下去. 先判断后执行.

do-while 循环
适合至少需要执行一次的情况, 不常用.
语法:
初始化;
do{
循环体;
}while(循环条件)//循环条件: boolean表达式.
先执行一遍语句, 当值为 true 时, 再次执行. 先执行后判断
区分:
do-while 结构的循环体至少会执行一次, 而 while 结构不会
do-while 先执行后判断, while 先判断后执行.

例: 当结果累积到 10 时, 输出结果.
//while 循环:
int sum = 0;
int i = 1;
do{
sum+=i;
i++;
}while(i<=10);
System.out.println("sum:"+sum);
//do-while 循环:
int sum = 0;
int i = 1;
do{
sum+=i;
i++;
}while(i<=10);
System.out.println("sum:"+sum);
for 循环
适合未知循环次数的情况.
语法:
for(初始化;循环条件;迭代){
循环体;
}
支持迭代, 最有效, 最通用的循环结构.
循环的次数在执行前便已确定.
-
初始化部分可以同时初始化多个变量.
-
当循环条件部分的值为
true, 则会进行循环. -
初始化, 循环条件, 迭代部分均分别可以是空语句 (会死循环).
补充: 在 IDEA 里有一组快捷键快捷输入 for 循环结构:
数字.fori, 快速输入for (int i = 100; i > 0; i--){}.
数字.forr, 快速输入for (int i = 100; i > 0; i--) {}.

应用: 打印 1~100 内的所有奇数和与偶数和.
public class Demo7 {
public static void main(String[] args) {
int oddSum = 0;
int evenSum = 0;
for (int i = 0; i <100 ; i++) {
if (i % 2 == 0){//趋于为 0,则为整数
evenSum += i;
}else{
oddSum += i;
}
}
System.out.println("奇数和 " + oddSum);
System.out.println("偶数和 " + evenSum);
}
}
输出九九乘法表:
public class Homework4 {
public static void main(String[] args) {
for (int j = 1; j <= 9; j++) {//j 是"乘数", 也是列号
for (int i = 1; i <= j; i++) {//i 是"被乘数", 也是行号; 1 <= j 使每行被乘数不大于乘数
System.out.print(i + "*" + j + "=" + (i * j) + "\t");
}
System.out.println();
}
}
}
输出结果:

补充:
System.out.print 打印不换行
转义字符: \n 换行, \t 制表符对齐
增强 for 循环
一种简化写法, 遍历组内的元素 (对集合中的每个元素执行以下操作).
用于数组和数列.
语法:
for (数据类型 变量名: 遍历的目标){
循环体;
}
两种循环的对比:
int[] numbers = {1, 2, 3, 4, 5};//定义一个数组.
//普通for循环:
for (int i = 0; i < 5; i++) {
System.out.println(numbers[i]);
}
//增强for循环
for (int x : numbers) {
System.out.println(x);//遍历数列
}
输出

又如:
public class Demo8 {
public static void main(String[] args) {
String[] places = {"Shanghai", "Tokyo", "Seoul"};
for (String destination : places){
System.out.println(destination);
}
}
}
输出

跳转语句
break
用于循环结构和 switch 结构.
程序遇到 break 时, 跳出循环, 然后执行循环后的语句.
continue
只能用于循环结构.
程序遇到 continue 时, 结束这一次的循环 (跳过剩下的语句), 并且直接进入下一次的循环.
带标签的 break 和 continue
上述提到的 break, continue 只能跳过当前的循环, 不能跨层操作.
通过在外层循环前添加标签, 可以实现对特定层次的精确控制.
带标签的 break: 中止整个标签块, 执行后面的语句.
带标签的 continue: 跳过标签循环的这一次迭代, 直接进行下一次迭代.
举两个直观的例子:
outer: for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
if (i == 1 && j == 1) {
break outer; //break 跳出整个标签循环
}
System.out.println("i=" + i + ", j=" + j);
}
}
输出不会把 i=1, j=1 和之后的结果打印:

此外:
outer: for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
if (i == 1 && j == 1) {
continue outer; // 跳过当前 i=1 的剩余迭代,直接进入 i=2
}
System.out.println("i=" + i + ", j=" + j);
}
}
输出只不会打印 i=1, j=1, 但是除此以外的都输出了

需要留意的是, 过多使用标签会导致代码可读性下降,需要克制使用 (可以减少嵌套层级以避免复杂逻辑).
return
用于结束一个方法.
当一个方法执行到一个 return 语句时, 不论它在哪个层级, 这一整个方法都会中止.
它更重要的作用时从方法中返回值, 之后再展开学习.
三者的区别
| 跳转语句 | 使用范围 | 作用 |
|---|---|---|
| break | while, do-while, for, switch |
结束所在循环. |
| continue | while, do-while, for |
结束本次循环,进行下一次循环. |
| return | - | 结束整个方法. |
练习: 打印一个 5 行的三角形
把三角形分成: 空格部分, 左半边, 右半边, 分别打印:
public class homework6 {
public static void main(String[] args) {
for (int i = 1; i <= 5; i++) {//行数最大到 5.
for (int j = 5; j >= i; j--) {//打印空格, 与行数反着来.
System.out.print(" ");
}
for (int j = 1; j <= i; j++) {//打印左半边, 有多少行打多少个.
System.out.print("*");
}
for (int j = 1; j < i; j++) {//打印右半边, 打印的个数比行数少 1.
System.out.print("*");
}
System.out.println();
}
三角形部分是: 左半边 (行数) + 右半边 (行数 - 1).
也可以写在一块, 就是打印 2 倍的行数 - 1 了:
public class homework5 {
public static void main(String[] args) {
for (int i = 1; i <= 5; i++) {
for (int j = 5; j >= i; j--) {//打印空格.
System.out.print(" ");
}
for (int k = 1; k <= 2 * i - 1; k++) {//打印三角形 行数 * 2 - 1
System.out.print("*");
}
System.out.println();
}
}
}
两个的结果是都是这样:


浙公网安备 33010602011771号