Java流程控制
# 流程控制
顺序结构
Java的基本结构就是顺序结构,一般从上到下一句一句执行
它是任何一个算法都离不开的一种基本算法结构
public class SequenceFlow {
public static void main(String[] args) {
System.out.println("从上到下执行");
System.out.println("先输出1");
System.out.println("2");
System.out.println("3");
System.out.println("4");
System.out.println("最后输出5");
System.out.println("结束");
}
}
选择结构
if单选择
if(布尔表达式)
{
//如果布尔表达式为true将执行的语句
}
if双选择
if(布尔表达式){
//如果布尔表达式的值为true
}else{
//如果布尔表达式的值为false
}
if多选择
if(布尔表达式 1){
//如果布尔表达式 1的值为true执行代码
}else if(布尔表达式 2){
//如果布尔表达式 2的值为true执行代码
}else if(布尔表达式 3){
//如果布尔表达式 3的值为true执行代码
}else {
//如果以上布尔表达式都不为true执行代码
}
嵌套if
if(布尔表达式 1){
////如果布尔表达式 1的值为true执行代码
if(布尔表达式 2){
////如果布尔表达式 2的值为true执行代码
}
}
多选择结构
switch case 语句语法
switch(expression){
case value :
//语句
break; //可选
case value :
//语句
break; //可选
//你可以有任意数量的case语句
default : //可选
//语句
}
switch case 语句有如下规则:
-
switch 语句中的变量类型可以是: byte、short、int 或者 char。
从 Java SE 7 开始,switch 支持字符串 String 类型了,同时 case 标签必须为字符串常量或字面量。
-
switch 语句可以拥有多个 case 语句。每个 case 后面跟一个要比较的值和冒号。
-
case 语句中的值的数据类型必须与变量的数据类型相同,而且只能是常量或者字面常量。
-
当变量的值与 case 语句的值相等时,那么 case 语句之后的语句开始执行,直到 break 语句出现才会跳出 switch 语句。
-
当遇到 break 语句时,switch 语句终止。程序跳转到 switch 语句后面的语句执行。case 语句不必须要包含 break 语句。如果没有 break 语句出现,程序会继续执行下一条 case 语句,直到出现 break 语句。
-
switch 语句可以包含一个 default 分支,该分支一般是 switch 语句的最后一个分支(可以在任何位置,但建议在最后一个)。default 在没有 case 语句的值和变量值相等的时候执行。default 分支不需要 break 语句。
switch case 执行时,一定会先进行匹配,匹配成功返回当前 case 的值,再根据是否有 break,判断是否继续输出,或是跳出判断。
SwitchDemo.java
import javax.sound.midi.Soundbank;
public class SwitchDemo {
public static void main(String[] args) {
char grade = 'A';
switch (grade) {
case 'A':
System.out.println("优秀");
break;
case 'B':
System.out.println("良好");
break;
case 'C':
System.out.println("及格");
break;
case 'D':
System.out.println("难顶");
break;
default:
System.out.println("GG");
}
System.out.println("---------Java7之后支持字符串判断-----------");
String evaluate = "良好";
switch (evaluate) {
case "优秀":
System.out.println('A');
break;
case "良好":
System.out.println('B');
break;
case "及格":
System.out.println('C');
break;
case "难顶":
System.out.println('D');
break;
default:
System.out.println("GG");
}
}
}
结果
优秀
---------Java7之后支持字符串判断-----------
B
*反编译
通过IDEA查看.class文件
将该文件复制到源码文件目录下
SwitchDemo.class
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//
package com.study.control;
public class SwitchDemo {
public SwitchDemo() {
}
public static void main(String[] args) {
char grade = 65;
switch(grade) {
case 65:
System.out.println("优秀");
break;
case 66:
System.out.println("良好");
break;
case 67:
System.out.println("及格");
break;
case 68:
System.out.println("难顶");
break;
default:
System.out.println("GG");
}
System.out.println("---------Java7之后支持字符串判断-----------");
String evaluate = "良好";
byte var4 = -1;
switch(evaluate.hashCode()) {
case 658856:
if (evaluate.equals("优秀")) {
var4 = 0;
}
break;
case 691634:
if (evaluate.equals("及格")) {
var4 = 2;
}
break;
case 1058030:
if (evaluate.equals("良好")) {
var4 = 1;
}
break;
case 1235320:
if (evaluate.equals("难顶")) {
var4 = 3;
}
}
switch(var4) {
case 0:
System.out.println('A');
break;
case 1:
System.out.println('B');
break;
case 2:
System.out.println('C');
break;
case 3:
System.out.println('D');
break;
default:
System.out.println("GG");
}
}
}
可以看到class文件自动生成了一个无参构造器
public SwitchDemo() {}
进行String匹配时,先用hasCode进行比较,再通过第二轮常规的switch匹配。
反编译以后再深入。
循环结构
while 循环
while是最基本的循环,它的结构为:
while(布尔表达式) {
//循环内容
}
注意:
-
只要布尔表达式为 true,循环就会一直执行下去。
-
我们大多数情况是会让循环停止下来的,我们需要一个让我们表达式失效的方式来结束循环。
-
少数情况下需要循环一直执行,比如服务器的请求响应监听等。
-
循环条件一直为true就会造成死循环。
do…while 循环
对于 while 语句而言,如果不满足条件,则不能进入循环。但有时候我们需要即使不满足条件,也至少执行一次。
do…while 循环和 while 循环相似,不同的是,do…while 循环至少会执行一次。
do {
//代码语句
}while(布尔表达式);
注意:布尔表达式在循环体的后面,所以语句块在检测布尔表达式之前已经执行了。
如果布尔表达式的值为 true,则语句块一直执行,直到布尔表达式的值为 false。
最后的分号不要忘记!
do...while适用于先输入再判断的情况。
如输入一串数据,遇到‘-1’结束
//输入一串数字,遇到 -1 结束
Scanner sc = new Scanner(System.in);
int num = 0;
do {
num = sc.nextInt();
System.out.println(num);
} while (num != -1);
结果
1 2 3 4 -1 5 6 7
1
2
3
4
-1
while 和 do...while 的区别
- while先判断后执行,do...while先执行后判断!
- do...while总是保证循环体至少被执行一次。while不一定执行。
for循环
虽然所有循环结构都可以用 while 或者 do...while表示,但 Java 提供了另一种语句 —— for 循环,使一些循环结构变得更加简单。
for循环执行的次数是在执行前就确定的。语法格式如下:
for(初始化; 布尔表达式; 更新) {
//代码语句
}
关于 for 循环有以下几点说明:
- 最先执行初始化步骤。可以声明一种类型,但可初始化一个或多个循环控制变量,也可以是空语句。
- 然后,检测布尔表达式的值。如果为 true,循环体被执行。如果为false,循环终止,开始执行循环体后面的语句。
- 执行一次循环后,更新循环控制变量。
- 再次检测布尔表达式。循环执行上面的过程。
for的流程图
增强 for 循环
Java5 引入了一种主要用于数组的增强型 for 循环。
Java 增强 for 循环语法格式如下:
for(声明语句 : 表达式)
{
//代码句子
}
声明语句:声明新的局部变量,该变量的类型必须和数组元素的类型匹配。其作用域限定在循环语句块,其值与此时数组元素的值相等。
表达式:表达式是要访问的数组名,或者是返回值为数组的方法。
public class EnhanceFor {
public static void main(String[] args) {
int[] numArray = {1, 2, 3, 4, 5, 6, 7, 8};
// numArray.for tab键
for (int i : numArray) {
System.out.println(i);
}
}
}
break 关键字
break 主要用在循环语句或者 switch 语句中,用来跳出整个语句块。
break 跳出最里层的循环,并且继续执行该循环下面的语句。
语法
break 的用法很简单,就是循环结构中的一条语句:
break;
public class BreakDemo {
public static void main(String[] args) {
for (int i = 0; i < 100; i++) {
if (i > 50) {
break;//i=51时就跳出循环,结束
}
System.out.println(i);
}
}
}
continue 关键字
continue 适用于任何循环控制结构中。作用是让程序立刻跳转到下一次循环的迭代。
在 for 循环中,continue 语句使程序立即跳转到更新语句。
在 while 或者 do…while 循环中,程序立即跳转到布尔表达式的判断语句。
语法
continue 就是循环体中一条简单的语句:
continue;
public class ContinueDemo {
public static void main(String[] args) {
for (int i = 0; i < 100; i++) {
if (i % 10 == 0) {
System.out.println();
continue;
}
// 每次遇到整除10的数就换行,同时跳出循环继续下一轮,略过整10的打印
System.out.print(i + "\t");
}
}
}
*GOTO语句(了解)
goto 关键字很早就在程序设计语言中出现。
事实上,goto 是汇编语言的程序控制结构的始祖:“若条件 A,则跳到这里;否则跳到那里”。
若阅读由几乎所有编译器生成的汇编代码,就会发现程序控制里包含了许多跳转。
然而,goto 是在源码的级别跳转的,所以招致了不好的声誉。
若程序总是从一个地方跳到另一个地方,还有什么办法能识别代码的流程呢?
随着 Edsger Dijkstra 著名的“Goto 有害”论的问世,goto 便从此失宠。
事实上,真正的问题并不在于使用 goto ,而在于 goto 的滥用。而且在一些少见的情况下,goto 是组织控制流程的最佳手段。
尽管 goto 仍是 Java 的一个保留字,但并未在语言中得到正式使用;Java 没有 goto 。
然而,在 break 和continue 这两个关键字的身上,我们仍然能看出一些 goto 的影子。
它并不属于一次跳转,而是中断循环语句的一种方法。之所以把它们纳入 goto 问题中一起讨论,是由于它们使用了相同的机制:标签。
“标签”是后面跟一个冒号的标识符,就象下面这样:
label1:
对 Java 来说,唯一用到标签的地方是在循环语句之前。进一步说,它实际需要紧靠在循环语句的前方——在
标签和循环之间置入任何语句都是不明智的。而在循环之前设置标签的唯一理由是:我们希望在其中嵌套另
一个循环或者一个开关。这是由于 break 和 continue 关键字通常只中断当前循环,但若随同标签使用,它们
就会中断到存在标签的地方。
下面是 for 循环的一个例子:
LabelDemo.java
package com.study.control;
/**
* 求100-1000的质素
*/
public class LabelDemo {
public static void main(String[] args) {
label:for (int i = 100; i <= 1000; i++) {
for (int j = 2; j <= i / 2; j++) {
if (i % j == 0) {
continue label; // 如果不是质素,跑到外层循环继续下一个数的判断
}
}
System.out.println(i);
}
}
}
练习
CirculationFlow.java
import java.util.Scanner;
/**
* 介绍三种循环
*/
public class CirculationFlow {
public static void main(String[] args) {
// 使用while循环计算1+2+3+...+100 =
int i = 1;
int sum = 0;
while (i <= 100) {
sum +=i;
i++;
}
System.out.println(sum);
// 使用do...while循环计算1+2+3+...+100 =
i = 1;
sum = 0;
do {
sum +=i;
i++;
}while (i <= 100);
System.out.println(sum);
// 使用for循环计算1+2+3+...+100
// 100.for tab键
sum = 0;
for (int j = 0; j < 100; j++) {
sum += (j+1);//j从0-99,需要+1变成1-100
}
System.out.println(sum);
}
}
ForDemo.java
/**
* 练习for的使用
*/
public class ForDemo {
public static void main(String[] args) {
// 输入1-1000能被5整除的数,并且每行打印三个。
for (int i = 1; i <= 1000; i++) {
if (i % 5 == 0) {
// print 不换行
System.out.print(i + "\t");
if (i % 3 == 0) {
//既能被5整除 又被3整除 换行
System.out.println();
}
}
}
// 打印99乘法表
System.out.println("\n------99乘法表--------");
for (int i = 1; i < 10; i++) {
for (int j = 1; j <= i; j++) {
System.out.print(j+"*"+i+"="+(i*j)+"\t");
}
System.out.println();
}
}
}
PrintTriangle.java
/**
* 打印三角形
*/
public class PrintTriangle {
public static void main(String[] args) {
int n = 5; // 行数 5
for (int i = 1; i <= n; i++) {
for (int j = n; j >= i; j--) {
System.out.print(" ");
}
for (int j = 1; j <= (2 * i - 1); j++) {
System.out.print("*");
}
System.out.println();
}
}
}
结果
*
***
*****
*******
*********