Java学习-3.流程控制语句

一、输入和输出

println是print line的缩写,表示输出并换行。因此,如果输出后不想换行,可以用print()

System.out.print("C.");
System.out.println();
System.out.println("END");

Java还提供了格式化输出的功能。为什么要格式化输出?因为计算机表示的数据不一定适合人来阅读:

public class Main {
    public static void main(String[] args) {
        double d = 12900000;
        System.out.println(d); // 1.29E7
    }
}

格式化输出:

格式化输出使用System.out.printf(),通过使用占位符%?printf()可以把后面的参数格式化成指定格式:

public class Main {
    public static void main(String[] args) {
        double d = 3.1415926;
        System.out.printf("%.2f\n", d); // 显示两位小数3.14
        System.out.printf("%.4f\n", d); // 显示4位小数3.1416
    }
}
占位符 说明
%d 格式化输出整数
%x 格式化输出十六进制整数
%f 格式化输出浮点数
%e 格式化输出科学计数法表示的浮点数
%s 格式化字符串

注意,由于%表示占位符,因此,连续两个%%表示一个%字符本身。

占位符本身还可以有更详细的格式化参数。下面的例子把一个整数格式化成十六进制,并用0补足8位。

int n = 12345000;
System.out.printf("n=%d, hex=%08x", n, n); // 注意,两个%占位符必须传入两个数
//n=12345000, hex=00bc5ea8

 

控制台输入:

import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in); // 创建Scanner对象
        System.out.print("Input your name: "); // 打印提示
        String name = scanner.nextLine(); // 读取一行输入并获取字符串
        System.out.print("Input your age: "); // 打印提示
        int age = scanner.nextInt(); // 读取一行输入并获取整数
        System.out.printf("Hi, %s, you are %d\n", name, age); // 格式化输出
    }
}

 

二、流程控制

流程控制语句分类:
    顺序结构
    选择结构
    循环结构

1. if语句

//if语句第一种格式:
if(关系表达式) {
		     语句体
	}
//关系表达式无论简单还是复杂,结果必须是boolean类型
//if语句控制的语句体如果是一条语句,大括号可以省略;如果是多条语句,就不能省略。建议永远不要省略。


//if语句第二种格式:
if(关系表达式) {
		     语句体1;
	}else {
		     语句体2;
	}


//if语句第三种格式:
if(关系表达式1) {
		     语句体1;
	}else  if (关系表达式2) {
		     语句体2;
	}
    …
	else {
		     语句体n+1;
	}

 

判断引用类型相等

在Java中,判断值类型的变量是否相等,可以使用==运算符。但是,判断引用类型的变量是否相等,==表示“引用是否相等”,或者说,是否指向同一个对象。例如,下面的两个String类型,它们的内容是相同的,但是,分别指向不同的对象,用==判断,结果为false

public static void main(String[] args) {
        String s1 = "hello";
        String s2 = "HELLO".toLowerCase();
        System.out.println(s1);
        System.out.println(s2);
        if (s1 == s2) {
            System.out.println("s1 == s2");
        } else {
            System.out.println("s1 != s2");  //运行
        }
    }

要判断引用类型的变量内容是否相等,必须使用equals()方法。

注意:执行语句s1.equals(s2)时,如果变量s1null,会报NullPointerException。

要避免NullPointerException错误,可以利用短路运算符&&

public class Main {
    public static void main(String[] args) {
        String s1 = null;
        if (s1 != null && s1.equals("hello")) {
            System.out.println("hello");
        }
    }
}

还可以把一定不是null的对象"hello"放到前面:例如:if ("hello".equals(s)) { ... }

要注意浮点数判断相等不能直接用==运算符;

引用类型判断内容相等要使用equals(),注意避免NullPointerException

 

2. Switch语句

//switch语句格式:
switch(表达式) {  //表达式的取值:byte,short,int,char,JDK5以后可以是枚举,JDK7以后可以是String。字符串匹配时,是比较“内容相等”。
	      case 值1://case后面跟的是要和表达式进行比较的值
			语句体1;
			break; //break表示中断,结束的意思,可以结束switch语句
		  case 值2:
			语句体2;
			break;
		    …
		  default://default语句表示所有情况都不匹配的时候,就执行该处的内容
			语句体n+1;
			break;
}
/*
注意事项:
    case后面只能是常量,不能是变量,而且,多个case后面的值不能出现相同的
default可以省略吗?
    可以省略。一般不建议。除非判断的值是固定的。(单选题)
break可以省略吗?
    可以省略,一般不建议。否则结果可能不是你想要的
default的位置一定要在最后吗?
    可以出现在switch语句任意位置。
switch语句的结束条件
    遇到break
    执行到程序的末尾
    
if语句使用场景:
    针对结果是boolean类型的判断
    针对一个范围的判断
    针对几个常量值的判断
switch语句使用场景:
    针对几个常量值的判断
*/

 

编译检查

使用IDE时,可以自动检查是否漏写了break语句和default语句,方法是打开IDE的编译检查。

在Eclipse中,选择Preferences - Java - Compiler - Errors/Warnings - Potential programming problems,将以下检查标记为Warning:

  • 'switch' is missing 'default' case
  • 'switch' case fall-through

在Idea中,选择Preferences - Editor - Inspections - Java - Control flow issues,将以下检查标记为Warning:

  • Fallthrough in 'switch' statement
  • 'switch' statement without 'default' branch

 

从Java 12开始,switch语句升级为更简洁的表达式语法,使用类似模式匹配(Pattern Matching)的方法,保证只有一种路径会被执行,并且不需要break语句:

//增强型
public class Main {
    public static void main(String[] args) {
        String fruit = "apple";
        switch (fruit) {
        case "apple" -> System.out.println("Selected apple");
        case "pear" -> System.out.println("Selected pear");
        case "mango" -> {
            System.out.println("Selected mango");
            System.out.println("Good choice!");
        }
        default -> System.out.println("No fruit selected");
        }
    }
}

注意新语法使用->,如果有多条语句,需要用{}括起来。不要写break语句,因为新语法只会执行匹配的语句,没有穿透效应。

 

很多时候,我们还可能用switch语句给某个变量赋值。 

int opt;
switch (fruit) {
case "apple":
    opt = 1;
    break;
case "pear":
case "mango":
    opt = 2;
    break;
default:
    opt = 0;
    break;
}

使用新的switch语法,不但不需要break,还可以直接返回值。把上面的代码改写如下:

public class Main {
    public static void main(String[] args) {
        String fruit = "apple";
        int opt = switch (fruit) {
            case "apple" -> 1;
            case "pear", "mango" -> 2;
            default -> 0;
        }; // 注意赋值语句要以;结束
        System.out.println("opt = " + opt);
    }
}

 

yield

大多数时候,在switch表达式内部,我们会返回简单的值。

但是,如果需要复杂的语句,我们也可以写很多语句,放到{...}里,然后,用yield返回一个值作为switch语句的返回值:

public class Main {
    public static void main(String[] args) {
        String fruit = "orange";
        int opt = switch (fruit) {
            case "apple" -> 1;
            case "pear", "mango" -> 2;
            default -> {
                int code = fruit.hashCode();
                yield code; // switch语句返回值
            }
        };
        System.out.println("opt = " + opt);
    }
}

 从Java 14开始,switch语句正式升级为表达式,不再需要break,并且允许使用yield返回值。

 

3. while循环

//while循环在每次循环开始前,首先判断条件是否成立。
//如果计算结果为true,就把循环体内的语句执行一遍,如果计算结果为false,那就直接跳到while循环的末尾,继续往下执行。
while (条件表达式) {
    循环语句
}
// 继续执行后续代码
//注意到while循环是先判断循环条件,再循环,因此,有可能一次循环都不做。
//如果循环条件永远满足,那这个循环就变成了死循环。死循环将导致100%的CPU占用,用户会感觉电脑运行缓慢,所以要避免编写死循环代码


 public static void main(String[] args) {
        int sum = 0;
        int n = 1;
        while (n > 0) {
            sum = sum + n;
            n ++;
        }
        System.out.println(n); // -2147483648
        System.out.println(sum);
    }
//表面上看,上面的while循环是一个死循环,但是,Java的int类型有最大值,达到最大值后,再加1会变成负数,结果,意外退出了while循环。

 

4. do while循环

//while循环是先判断循环条件,再执行循环。而另一种do while循环则是先执行循环,再判断条件,条件满足时继续循环,条件不满足时退出。
do {
    执行循环语句
} while (条件表达式)
    
/*注意事项:
写程序优先考虑for循环,再考虑while循环,最后考虑do…while循环。
如下代码是死循环
while(true){}
for(;;){}
*/

 

5. for循环

//for循环的功能非常强大,它使用计数器实现循环。
//for循环会先初始化计数器,然后,在每次循环前检测循环条件,在每次循环后更新计数器。计数器变量通常命名为i。

for (初始条件; 循环检测条件; 循环后更新计数器) {
    // 执行语句
}
//注意for循环的初始化计数器总是会被执行,并且for循环也可能循环0次。

//使用for循环时,千万不要在循环体内修改计数器!在循环体中修改计数器常常导致莫名其妙的逻辑错误。对于下面的代码:
public class Main {
    public static void main(String[] args) {
        int[] ns = { 1, 4, 9, 16, 25 };
        for (int i=0; i<ns.length; i++) {
            System.out.println(ns[i]);  // 1 9 25
            i = i + 1;
        }
    }
}

for each循环

增强for循环

public class Main {
    public static void main(String[] args) {
        int[] ns = { 1, 4, 9, 16, 25 };
        for (int n : ns) {
            System.out.println(n);
        }
    }
}
//和for循环相比,for each循环的变量n不再是计数器,而是直接对应到数组的每个元素。
//for each循环的写法也更简洁。但是,for each循环无法指定遍历顺序,也无法获取数组的索引。

 

6. break和continue 

break:跳出当前循环

continue:跳出本次循环

return:返回

 

posted @ 2023-07-29 18:30  highlightyys  阅读(6)  评论(0编辑  收藏  举报