Java基础-流程控制



1. 输入和输出

输出

System.out.println(),其中println(print line)表示输出并换行,不想换行可使用print()

System.out.printf()为格式化输出,可通过%?占位符来替换输出内容:

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:格式化字符串/li>

更多详细内容,参考JDK文档:java.util.Formatter

输入

Java中的输入需要通过import导入java.util.Scanner包:

package demo;

import java.util.Scanner;

public class Input {
  public static void main(String[] args) {
    Scanner scanner = new Scanner(System.in);
    System.out.print("Input your name: ");
    String name = scanner.nextLine();
    System.out.printf("your name is: %s", name);
  }
}


2. if判断

基本语法:

if (条件) {
    // 条件满足时执行
}

其中条件表示式计算结果需要是truefalse,JVM会根据计算结果决定是否执行{}内的语句块。

if语句块只有一行时,可以省略{}

public class Main {
    public static void main(String[] args) {
        int n = 70;
        if (n >= 60)
            System.out.println("及格了");
        System.out.println("END");
    }
}

注意:省略{}时使用版本控制系统合并代码时更容易出现问题,所以并不推荐省略{}

else

还可以为if编写一个else语句块(但并不是必须的),当条件表示式为false时会执行该语句块:

public class Main {
    public static void main(String[] args) {
        int n = 70;
        if (n >= 60) {
            System.out.println("及格了");
        } else {
            System.out.println("挂科了");
        }
        System.out.println("END");
    }
}


相等性判断

对于值类型来说可以用==来判断;但对于引用类型来说,==表示是否指向同一个对象。例如,以下两个字符串:

public class If {
  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");
    }
  }
}

以上示例中,虽然s1、s2对象值都是hello,但表达式计算结果为false。要判断引用类型的值是否相等,应使用equals()方法:

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


3. switch选择

当判断条件较多时,可使用switch表达时,其会根据不同的表达式计算结果,分别执行不同的分支:

public class Main {
    public static void main(String[] args) {
        int option = 1;
        switch (option) {
        case 1:
            System.out.println("Selected 1");
            break;
        case 2:
            System.out.println("Selected 2");
            break;
        case 3:
            System.out.println("Selected 3");
            break;
        default:
            System.out.println("Not selected");
            break;
        }
    }
}

在以上示例中,会根据option选择不同的执行case分支,如果所有条件都不配置,则会执行default分支。

如果用if表达式实现上述功能,则:

if (option == 1) {
    System.out.println("Selected 1");
} else if (option == 2) {
    System.out.println("Selected 2");
} else if (option == 3) {
    System.out.println("Selected 3");
} else {
    System.out.println("Not selected");
}

switch语句还可以匹配字符串。字符串匹配时,是比较“内容相等”。

public class Main {
    public static void main(String[] args) {
        String fruit = "apple";
        switch (fruit) {
        case "apple":
            System.out.println("Selected apple");
            break;
        case "pear":
            System.out.println("Selected pear");
            break;
        case "mango":
            System.out.println("Selected mango");
            break;
        default:
            System.out.println("No fruit selected");
            break;
        }
    }
}

从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语句。

->还可以直接返回值,例如:

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

可以简写为:

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

如果需要复杂的语句,我们也可以写很多语句,放到{...}里,然后,用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);
    }
}

switch表达式是作为Java 13的预览特性(Preview Language Features)实现的,编译的时候,我们还需要给编译器加上参数:

javac --source 13 --enable-preview Main.java


4. while循环

while循环会在满足条件表达式(true)时执行“循环语句”;不满足条件表达式时(false),继续执行后续代码。语法结构如下:

while (条件表达式) {
    循环语句
}
// 继续执行后续代码

如果循环条件永远满足,那这个循环就变成了死循环。死循环会导致100%的CPU占用,所以要避免编写死循环代码


5. do-while循环

while循环是先判断条件表达式do-while会先执行循环,再判断条件表达式,也就是说其循环会至少循环一次

public class Main {
    public static void main(String[] args) {
        int sum = 0;
        int n = 1;
        do {
            sum = sum + n;
            n ++;
        } while (n <= 100);
        System.out.println(sum);
    }
}


6. for循环

除了whiledo-while循环,还可以使用for循环。其语法如下:

for (初始条件; 循环检测条件; 循环后更新计数器) {
    // 执行语句
}

例如,对一个整型数组的所有元素求和:

public class Main {
    public static void main(String[] args) {
        int[] ns = { 1, 4, 9, 16, 25 };
        int sum = 0;
        for (int i=0; i<ns.length; i++) {
            System.out.println("i = " + i + ", ns[i] = " + ns[i]);
            sum = sum + ns[i];
        }
        System.out.println("sum = " + sum);
    }
}

for循环还可以缺少初始化语句、循环条件和每次循环更新语句,例如

// 不设置结束条件:
for (int i=0; ; i++) {
    ...
}

// 不设置结束条件和更新语句:
for (int i=0; ;) {
    ...
}

// 什么都不设置:
for (;;) {
    ...
}

for each循环

Java还提供了另一种for each循环,它可以更简单地遍历数组:

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 eachh循环的变量n不再是计数器,而是直接对应到数组的每个元素。for each循环的写法也更简洁。但是,for each循环无法指定遍历顺序,也无法获取数组的索引。

除了数组外,for each循环能够遍历所有“可迭代”的数据类型,包括后面会介绍的List、Map等。


7. breakcontinue

while循环和for循环中,可以使用breakcontinue语句。其中,break用于跳出当前循环;而continue用于结束本次循环,继续执行下次循环。