流程控制
输入输出
输出
Java中最经常使用的输出是System.out.println()
向控制台输出内容
println
是print line的缩写,表示输出换行。
格式化输出
为了方便人们阅读,Java提供了格式化输出功能。如下边事例:
public class Main {
public static void main(String[] args) {
double d = 12900000;
System.out.println(d); // 1.29E7
}
}
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
}
}
public class Main {
public static void main(String[] args) {
int n = 12345000;
System.out.printf("n=%d, hex=%08x", n, n); // 注意,两个%占位符必须传入两个数,结果:n=12345000, hex=00bc5ea8
}
}
复制代码
Java的格式化功能提供了多种占位符,可以把各种数据类型“格式化”成指定的字符串:
占位符 | 说明 |
---|---|
%d | 格式化输出整数(十进制) |
%c | Unicode字符 |
%b | Boolean值 |
%x | 格式化输出十六进制整数 |
%f | 格式化输出浮点数 |
%e | 格式化输出科学计算法表示的浮点数 |
%s | 格式化字符串 |
%h | 散列码(16进制) |
%% | 字符"%" |
-
printf()
int x =13; //传统输出 System.out.println("var x is"+x); // 使用printf();格式化输出 System.out.printf("var x is %d\n",x); 复制代码
-
format()
format();方法和printf();方法的使用都是一样的,参数都是一个格式化的字符串加上一个或者多个的字符串占位符填充,代码案例如下:
-
String.format()
在String类中,有一个静态方法String.format();,也能用于格式化字符串,它能接受和printf();、**format();**这两个方法一样的参数,在完成字符串格式化后,返回格式化后的字符串;案例代码如下:
不同于printf();、**format();**这两个方法的是,String.format()方法返回的是一个String对象,printf();、**format();**返回的是一个PrintStream对象,可直接用于打印输出。
Formatter类
无论是printf();
方法,还是format();
方法,亦或者String.format();
方法,他们的内部都是调用java.util.Formatter类
的format
方法来做格式化的;故,可以把Formatter
类看作一个翻译器,负责将占位符字符串与数据翻译成想要的结果。
由于底层都是使用Formatter类来做格式化处理的,所以我们也可以直接使用Formatter类来做格式化处理,直接调用Formatter类的format方法**,**案例代码如下:
输入
和输出相比,Java的输入就要复杂得多。我们先看一个控制台输入例子:
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); // 格式化输出
}
}
复制代码
创建Scanner
对象并传入System.in
标准输入,在通过scanner.nextLine()
读取用户输入,使用scanner.nextInt()
时,Scanner会自动转换数据类型,不需要手动转换。
if判断
Java 中条件判断语句if
if (条件) {
// 条件满足时执行
}
复制代码
先看一个例子:
当条件n >= 60
计算结果为true
时,if
语句块被执行,将打印"及格了"
,否则,if
语句块将被跳过。修改n
的值可以看到执行效果。
public class Main {
public static void main(String[] args) {
int n = 70;
if (n >= 60) {
System.out.println("及格了");
System.out.println("恭喜你");
}
System.out.println("END");
}
}
复制代码
当if
语句块只有一行语句时,可以省略花括号{}:
public class Main {
public static void main(String[] args) {
int n = 70;
if (n >= 60)
System.out.println("及格了");
System.out.println("END");
}
}
复制代码
但是,省略花括号并不总是一个好主意。假设某个时候,突然想给if
语句块增加一条语句时:
public class Main {
public static void main(String[] args) {
int n = 50;
if (n >= 60)
System.out.println("及格了");
System.out.println("恭喜你"); // 注意这条语句不是if语句块的一部分
System.out.println("END");
}
}
复制代码
由于使用缩进格式,很容易把两行语句都看成if
语句的执行块,但实际上只有第一行语句是if
的执行块。在使用git这些版本控制系统自动合并时更容易出问题,所以不推荐忽略花括号的写法。
else
if
语句还可以编写一个else { ... }
,当条件判断为false
时,将执行else
的语句块:
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");
}
}
复制代码
判断浮点数
假设我们期望90分或更高为“优秀”,上述代码输出的却是“及格”,原因是>
和>=
效果是不同的。前面讲过了浮点数在计算机中常常无法精确表示,并且计算可能出现误差,因此,判断浮点数相等用==
判断不靠谱:
public class Main {
public static void main(String[] args) {
double x = 1 - 9.0 / 10;
if (x == 0.1) {
System.out.println("x is 0.1");
} else {
System.out.println("x is NOT 0.1");
}
}
}
复制代码
正确的方法是利用差值小于某个临界值来判断:
public class Main {
public static void main(String[] args) {
double x = 1 - 9.0 / 10;
if (Math.abs(x - 0.1) < 0.00001) {
System.out.println("x is 0.1");
} else {
System.out.println("x is NOT 0.1");
}
}
}
复制代码
判断引用类型相等
在Java中,判断值类型的变量是否相等,可以使用==
运算符。但是,判断引用类型的变量是否相等,==
表示“引用是否相等”,或者说,是否指向同一个对象。例如,下面的两个String类型,它们的内容是相同的,但是,分别指向不同的对象,用==
判断,结果为false
public class Main {
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");
}
}
}
// 结果
hello
hello
s1 != s2
复制代码
要判断引用类型的变量内容是否相等,必须使用equals()
方法:
public class Main {
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 equals s2");
} else {
System.out.println("s1 not equals s2");
}
}
}
//结果
hello
hello
s1 equals s2
复制代码
注意:执行语句s1.equals(s2)
时,如果变量s1
为null
,会报NullPointerException
:
public class Main {
public static void main(String[] args) {
String s1 = null;
if (s1.equals("hello")) {
System.out.println("hello");
}
}
}
复制代码
要避免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)) { ... }
。
switch 多重选择
switch
语句根据switch (表达式)
计算的结果,跳转到匹配的case
结果,然后继续执行后续语句,直到遇到break
结束执行。
switch (option) { case 3: ... break; case 2: ... break; case 1: ... break; default: ... break; } 复制代码
事例:
public class Main {
public static void main(String[] args) {
int option = 99;
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;
}
}
}
复制代码
while和do while循环
while (条件表达式) {
循环语句
}
// 继续执行后续代码
do {
执行循环语句
} while (条件表达式);
复制代码
事例:
while:
public class Main {
public static void main(String[] args) {
int sum = 0; // 累加的和,初始化为0
int n = 1;
while (n <= 100) { // 循环条件是n <= 100
sum = sum + n; // 把n累加到sum中
n ++; // n自身加1
}
System.out.println(sum); // 5050
}
}
复制代码
do while:
public class Main {
public static void main(String[] args) {
int sum = 0;
int m = 20;
int n = 100;
// 使用do while计算M+...+N:
do {
} while (false);
System.out.println(sum);
}
}
复制代码
for循环
除了while
和do while
循环,Java使用最广泛的是for
循环。
for (初始条件; 循环检测条件; 循环后更新计数器) {
// 执行语句
}
复制代码
数组变量
int[] ns = { 1, 4, 9, 16, 25 };
for (int i=0; i<ns.length; i++) {
System.out.println(ns[i]);
}
复制代码
但是,很多时候,我们实际上真正想要访问的是数组每个元素的值。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 each
循环的变量n不再是计数器,而是直接对应到数组的每个元素。for each
循环的写法也更简洁。但是,for each
循环无法指定遍历顺序,也无法获取数组的索引。
除了数组外,for each
循环能够遍历所有“可迭代”的数据类型,包括后面会介绍的List
、Map
等。
break和continue
无论是while
循环还是for
循环,有两个特别的语句可以使用,就是break
语句和continue
语句。
break
在循环过程中,可以使用break
语句跳出当前循环。我们来看一个例子:
public class Main {
public static void main(String[] args) {
int sum = 0;
for (int i=1; ; i++) {
sum = sum + i;
if (i == 100) {
break;
}
}
System.out.println(sum);
}
}//结果:5050
复制代码
continue
break
会跳出当前循环,也就是整个循环都不会执行了。而continue
则是提前结束本次循环,直接继续执行下次循环。我们看一个例子:
public class Main {
public static void main(String[] args) {
int sum = 0;
for (int i=1; i<=10; i++) {
System.out.println("begin i = " + i);
if (i % 2 == 0) {
continue; // continue语句会结束本次循环
}
sum = sum + i;
System.out.println("end i = " + i);
}
System.out.println(sum); // 25
}
}
/*结果
begin i = 1
end i = 1
begin i = 2
begin i = 3
end i = 3
begin i = 4
begin i = 5
end i = 5
begin i = 6
begin i = 7
end i = 7
begin i = 8
begin i = 9
end i = 9
begin i = 10
25
/*
复制代码
总结
System.out.println()
是最常用的输出,也可以使用占位符格式化输出;输出经常使用Scanner
对象- 判断语句使用if,注意判断浮点数条件、变量为
null
情况下的判断 - 循环语句使用while、do while、for语句,并且注意break和continue的使用。