Hi i,m JinXiang ⭐ 前言 ⭐ 本篇文章主要介紹Java時間的幾種常見方法以及部分理論知識 🍉歡迎點贊 👍 收藏 ⭐留言評論 📝私信必回喲😁 🍉博主收將持續更新學習記錄獲,友友們有任何問題可以在評論區留言 ⭐什麼是Date日期類型? 在JDK1.0中,Date類是唯一的一個代 ...
本文中使用到的工具是Intellij IDEA和JDK 8,需要安裝兩款工具的請查看這兩篇教程:點我查看安裝JDK8/11/17教程、點我查看安裝Intellij IDEA教程。
前面我們寫過的代碼,都是在main
方法中自上到下按順序執行的,舉一個代碼慄子:
/**
* 計算西瓜的價格
*
* @author iCode504
* @date 2023-10-31
*/
public class MyWatermelonDemo1 {
public static void main(String[] args) {
int price = 2; // 西瓜的單價
int weight = 10; // 西瓜的重量(公斤)
int totalPrice = price * weight; // 購買價格
System.out.println("西瓜的價格是: " + totalPrice + "元");
}
}
這段代碼就是先定義西瓜的單價、再定義西瓜的重量,然後計算西瓜的價格,最後對價格進行輸出。像這樣代碼從上到下執行的結構就是順序結構。
程式一共有三種控制結構:順序結構、選擇結構和迴圈結構。其中選擇結構是根據條件判定的結果,選擇執行不同的代碼,例如:紅燈停,綠燈行。判斷條件就是交通信號燈的狀態。
Java也有選擇結構,並且有多種類型的條件判斷語句:單分支的if
語句、雙分支的if-else
語句、多分支的if-else if-else
語句、if
嵌套語句和switch
語句。
一、單分支if語句
單分支if
語句的語法如下:
if (條件表達式) {
執行代碼...
}
其中條件表達式的計算結果必須是boolean
類型。如果條件表達式的計算結果是true
,那麼就會執行if
內部的代碼;如果表達式為false
,此時就會跳過if
代碼塊(也就是if
內部代碼不執行),概念圖如下:
我們可以在if
代碼塊中可以編寫多個執行語句。
以下是if
的使用案例:
案例:之前長春下了大暴雪,氣溫驟降,我想在某寶上買幾雙棉襪子,假設每雙襪子4元,請確保輸入的數字大於0再計算購買價格。
分析:解題的關鍵在於要保證輸入的數字要大於0,因此要判斷輸入的數字是否大於0,示例代碼如下:
import java.util.Scanner;
/**
* if條件判斷
*
* @author iCode504
* @date 2023-11-07
*/
public class IfDemo1 {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println("請輸入襪子的數量");
int count = scanner.nextInt();
double totalPrice = 0.0; // 預設總價格初始值為0.0
double price = 4; // 襪子的價格4元
// 條件判斷: 輸入的數量是否大於0
if (count > 0) {
totalPrice = count * price;
System.out.println("購買了" + count + "雙襪子, 價格是" + totalPrice + "元");
}
}
}
運行結果:
案例:輸入一個數字,如果能被10整除,則輸出內容為:xx能被10整除。如果能被15整除,則輸出內容為:xx能被15整除。
解決本題的關鍵點在於被10整除和被15整除的條件怎麼計算。其實前面我們學過取餘運算符,如果數值number
能被10整除,那麼可以寫成number % 10 == 0
;如果數值number
能被15整除,那麼可以寫成number % 15 == 0
。這兩個布爾表達式可以寫入到兩個if
語句中:
import java.util.Scanner;
/**
* 使用if語句判斷數字能否被10和15整除
*
* @author iCode504
* @date 2023-11-07
*/
public class IfDemo2 {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println("請輸入數字: ");
int number = scanner.nextInt();
// 整除10的條件:數字對10取餘等於0
if (number % 10 == 0) {
System.out.println(number + "能被10整除");
}
// 整除15的條件:數字對15取餘等於0
if (number % 15 == 0) {
System.out.println(number + "能被15整除");
}
}
}
輸入不同的數字以後,會得到如下的運行結果:
案例:輸入兩個整數,如果輸入的第一個數字比第二個數字大,那麼執行兩數交換,並將交換結果輸出。否則不交換,正常輸出兩個數
本題的條件表達式是輸入的兩個數字的比較,無論數字大小比較結果如何,都需要將結果進行輸出,我們可以將輸出語句放到if
語句後面執行。
兩數交換有多種方式,較為穩妥的方式是再定義一個臨時變數,用這個臨時變數來接收第一個變數值,然後第二個變數值賦值給第一個變數,最後將臨時變數的值賦值給第二個變數。
以下是示例代碼:
import java.util.Scanner;
/**
* 單分支if語句實現兩數交換
*
* @author iCode504
* @date 2023-11-11
*/
public class IfDemo3 {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println("請輸入兩個整數");
int number1 = scanner.nextInt();
int number2 = scanner.nextInt();
int temp = 0; // 定義臨時變數
if (number1 > number2) { // 實現兩數交換功能
temp = number1;
number1 = number2;
number2 = temp;
}
System.out.println("第一個數是: " + number1 + ", 第二個數是: " + number2);
}
}
運行結果:
當然,除了上述方式能實現兩數交換,還有其他的方式。
方式一:使用加減法進行交換(推薦使用整數,浮點數不推薦,因為浮點數計算時會出現誤差)
int number1 = 3;
int number2 = 2;
number1 = number1 + number2; // number1 = 3 + 2 = 5
number2 = number1 - number2; // number2 = 5 - 2 = 3
number1 = number1 - number2; // number1 = 5 - 3 = 2
方式二:使用位運算符進行交換(推薦使用整數,此處涉及到二進位異或運算,異或運算可以查看這篇文章:入門篇-其之六-Java運算符(中)第四部分-位運算符)
int number1 = 3;
int number2 = 2;
number1 = number1 ^ number2; // 3 ^ 2 = 1
number2 = number1 ^ number2; // 3 ^ 1 = 2
number1 = number1 ^ number2; // 1 ^ 2 = 3
當然,上述三種方式我個人最推薦的還是第一種定義臨時變數的方式,這種方式對處理浮點類型的數進行交換很友好,如果使用了下麵兩種方式的話,可能會在計算過程中出現精度損失的問題。後兩種方式的好處是不需要定義第三個變數,只需要進行一系列運算即可完成整數值的交換。
二、if-else雙分支語句
前面講過的單分支if
語句只有在布爾表達式為true
的時候執行其內部的內容,但是如果在布爾表達式為false
的時候不會做任何事情。為瞭解決上述問題,Java為我們提供了if-else
雙分支語句。以下是雙分支if-else
語句代碼結構:
if (條件表達式) {
執行代碼1...
} else {
執行代碼2...
}
如果條件表達式的值是true
,那麼就執行if
內部的語句,如果條件表達式為false
,此時就進入else
代碼塊。執行流程圖如下:
案例:我們還是以上述買襪子為例,最近雙十一打折,如果買了10雙及以上襪子,此時每雙襪子打八折優惠,否則打九折優惠(襪子的價格假設是4元/雙)。
題目中的條件表達式在於要買的襪子數量是否大於等於10,如果是,價格打8折,否則打9折,使用剛剛講到的if-else
語句即可搞定。
當然,這道題中還有一個隱藏的細節需要我們處理:輸入襪子的數量需要大於0,否則判定為無效,這個可以使用單分支if
語句就可以搞定。
以下是示例代碼:
import java.util.Scanner;
/**
* if-else雙分支語句
*
* @author iCode504
* @date 2023-11-11
*/
public class IfDemo4 {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println("請輸入要購買的襪子數量");
int count = scanner.nextInt();
double price = 4; // 每雙襪子的價格
double totalPrice = 0.0; // 預設總價格為0.0
// 需要保證輸入的襪子數量要大於0
if (count > 0) {
// 如果襪子的數量大於10,此時每雙襪子的價格為8折,即每雙襪子的價格乘以0.8,九折的計算方式和上述內容同理
if (count >= 10) {
totalPrice = price * 0.8 * count;
} else {
totalPrice = price * 0.9 * count;
}
}
System.out.println("購買" + count + "雙襪子,雙十一期間購買價格是" + totalPrice + "元");
}
}
運行結果(可能會出現浮點數計算不准確的情況,屬於正常現象):
三、if-else if-else多分支語句
雙分支的if-else
語句對於條件表達式為true
和false
的時候比較適用,但是如果對於一個問題而言,此時經過分析可能存在多個條件表達式時,if-else
語句並不能很好地完成任務,此時Java為我們提供了另一種分支語句:if-else if-else
語句,其語法格式如下:
if (條件表達式1) {
執行代碼1...
} else if (條件表達式2) {
執行代碼2...
} else if (條件表達式3) {
執行代碼3...
} ...
else if (條件表達式n) {
執行代碼n...
} else {
不符合上述所有條件表達式時執行else代碼...
}
以上述語法格式為例,其執行順序為:
- 如果條件表達式1的結果為
true
,那麼執行代碼1,如果結果是false
,此時就會跳轉到第一個else if
。 - 如果條件表達式2的結果是
true
,那麼執行代碼2,如果結果是false
,那麼就會跳轉到第二個else if
。 - 如果條件表達式3的結果是
true
,那麼執行代碼3,如果結果是false
,那麼就會跳轉到下一個else if
,依次類推。 - 當上述所有的條件表達式都不滿足(即結果全部是
false
)時,就會執行else
中的語句。
多分支的if-else if-else
語句中,你可以寫任意個else if
,每個else if
需要寫上條件表達式。
當然,最後的else
也是可選的,if
和else-if
搭配使用也是可以的。以下是執行流程圖:
案例:已知長春的地鐵/輕軌票價標準如下
- 0-7公裡(含7公裡),票價2元;
- 7-13公裡(含13公裡),票價3元;
- 13-19公裡(含19公裡),票價4元;
- 19-27公裡(含27公裡),票價5元;
- 27-35公裡(含35公裡),票價6元;
- 35公裡以上每增加10公裡,增加1元
假設從1號線紅嘴子地鐵站到8號線廣通路輕軌站的距離是31.4公裡,從2號線汽車公園地鐵站到2號線東方廣場地鐵站的距離是20.5公裡,從4號線長春站北輕軌站到4號線天工路輕軌站的距離是16.3公裡。
輸入上述里程,利用程式計算出乘坐軌道交通所需要的票價。
上述題目中出現了多個條件判斷,每個條件判斷執行內容都不相同,使用多分支語句if-else if-else
語句比較合適。題目中有一個隱藏條件,輸入里程數不能為負數,當然這個條件也直接寫入條件判斷即可。
如果乘坐軌道交通的里程超過35公裡以後,每增加10公裡,增加1元。例如:乘坐45公裡就要在35公裡對應的票價6元的基礎上再增加1元,當然,55公裡、65公裡依次類推。假設稱作里程為44.9公裡,此時收費標準仍為35公裡的票價。
針對上述問題,我們可以在代碼中進一步呈現:
import java.util.Scanner;
/**
* if-else if-else多分支語句的使用
*
* @author iCode504
* @date 2023-11-14
*/
public class ElseIfDemo1 {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.print("請輸入里程數: ");
// 里程數使用double類型比較合適,因為題目中涉及到距離的使用到了小數
double distance = scanner.nextDouble();
int price = 0;
if (distance <= 0) {
System.out.println("無效里程");
} else if (distance > 0 && distance <= 7) {
price = 2;
} else if (distance > 7 && distance <= 13) {
price = 3;
} else if (distance > 13 && distance <= 19) {
price = 4;
} else if (distance > 19 && distance <= 27) {
price = 5;
} else if (distance > 27 && distance <= 35) {
price = 6;
} else {
// 超過35公裡的需要額外進行處理
price = 6; // 35公裡對應的票價
// 計算多餘的里程
// 這裡需要進行強制類型轉換的目的有兩個:
// 1. 最後計算票價的price是int類型
// 2. 針對類似在35~45公裡之間的里程後續的票價計算處理
int additionalDistance = (int) (distance - 35);
// 計算票價
price = price + additionalDistance / 10;
}
System.out.println("乘坐長春軌道交通里程" + distance + "公裡,票價" + price + "元");
}
}
運行結果如下:
四、if的嵌套使用
正如標題所講,if
語句可以嵌套使用。舉個慄子:在main
方法中,假設已經存在了一個if-else
語句,那麼在這個if
代碼塊或者else
代碼塊還可以存在條件判斷語句,下麵就是其中一種if
的嵌套使用方式(事實上它可以if
代碼塊可以進行多種組合嵌套使用):
if (條件表達式1) {
if (條件表達式2) {
執行代碼1...
} else {
執行代碼2...
}
} else {
if (條件表達式3) {
執行代碼3...
} else {
執行代碼4...
}
}
它的執行流程如下:
- 如果條件表達式1的執行結果是
true
,進入條件表達式2,如果條件表達式2執行結果是true
,此時執行代碼1。 - 如果條件表達式1的執行結果是
true
,進入條件表達式2,如果條件表達式2執行結果是false
,此時執行代碼2。 - 如果條件表達式1的執行結果是
false
,進入條件表達式3,如果條件表達式3執行結果是true
,此時執行代碼3。 - 如果條件表達式1的執行結果是
false
,進入條件表達式3,如果條件表達式3執行結果是false
,此時執行代碼4。
執行流程圖如下所示:
日常寫代碼的過程中,儘量保證代碼嵌套的層數不超過兩層。
案例:輸入三個數,要求輸出是按照從大到小進行排列。例如,輸入三個數為20、30、10,輸出結果為30、20、10
- 第一層條件:比較第一個數和第二個數。
- 第二層條件:比較第二個數和第三個數。
- 第三層條件:比較第一個數和第三個數。
import java.util.Scanner;
/**
* if的嵌套--三個數字排列
*
* @author iCode504
* @date 2023-11-23
*/
public class IfDemo5 {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.print("請輸入三個整數: ");
int number1 = scanner.nextInt();
int number2 = scanner.nextInt();
int number3 = scanner.nextInt();
if (number1 > number2) {
if (number2 > number3) {
System.out.println("三個數從大到小的排序是: " + number1 + " " + number2 + " " + number3);
} else {
if (number1 > number3) {
System.out.println("三個數從大到小的排序是: " + number1 + " " + number3 + " " + number2);
} else {
System.out.println("三個數從大到小的排序是: " + number3 + " " + number1 + " " + number2);
}
}
} else {
if (number2 < number3) {
System.out.println("三個數從大到小的排序是: " + number3 + " " + number2 + " " + number1);
} else {
if (number1 > number3) {
System.out.println("三個數從大到小的排序是: " + number2 + " " + number3 + " " + number1);
} else {
System.out.println("三個數從大到小的排序是: " + number2 + " " + number1 + " " + number3);
}
}
}
}
}
運行結果:
雖然運行結果符合我們的預期,但是我只能說:這樣的代碼寫的非常糟糕!!!這段代碼中if
的嵌套層數達到了三層,事實上if
嵌套兩層以上可讀性就大打折扣了。
我們可以使用Java數組、迴圈和數組方法對此問題做進一步處理(小白可以跳過這一部分)。
import java.util.Arrays;
import java.util.Scanner;
/**
* 三數比較--按照從大到小的順序排列
*
* @author iCode504
* @date 2023-11-23
*/
public class IfDemo6 {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.print("請輸入三個數字: ");
Integer[] array = new Integer[3];
for (int i = 0; i < array.length; i++) {
array[i] = scanner.nextInt();
}
// 調用Arrays.sort方法對數組排序,排序規則從大到小(lambda表達式)
Arrays.sort(array, (o1, o2) -> o2 - o1);
System.out.println("三個數從大到小的排序是: " + array[0] + " " + array[1] + " " + array[2]);
}
}
運行結果:
五、switch語句
if-else if-else
多分支語句可以用於多個條件表達式的判斷,我們可以寫非常多的else if
,然而過多的else if
可能會導致代碼的可讀性變差。
Java為我們提供了swtich
語句在一定程度上可以簡化多條件分支。以下是switch
的語法結構:
switch (表達式) {
case 值1:
執行代碼1...
break;
case 值2:
執行代碼2...
// break
case 值3:
執行代碼3...
break;
...
case 值n:
執行代碼n...
break;
default:
上述條件都不適用執行代碼...
}
1. switch
語句中表達式的計算結果、值1、值2、...、值n的數據類型必須要保持一致。支持的數據類型包括:byte
、short
、int
、char
、字元串類型String
(JDK 7新特性)、枚舉類型(後續會講到,JDK 7新特性)。
2. 如果表達式的計算結果和case
中某個值相等時,就會執行這個case
內的代碼。
3. switch
語句中的default
是可選的,它的作用是當表達式的計算結果和所有case
的值都不相等時才會執行default
語句,如果default
語句不存在時,所有的case
對應的值和判定值都不相等時,跳出switch
語句。
4. break
的作用是跳出switch
語句(break
關鍵字還會在迴圈中遇到),在每一個case
對應的代碼塊後面寫上break
是個好習慣。
如果case
中不加break
,此時switch
語句會出現穿透性,即當某一個case
執行完成後,它會繼續執行下麵其他的case
。以下是一個是否使用break
的案例:
案例:輸入數字1~7,使用
switch
語句輸出當前日期(假設7代表星期日)
import java.util.Scanner;
/**
* switch語句--不加break--穿透性
*
* @author iCode504
* @date 2023-11-15
*/
public class SwitchDemo1 {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println("請輸入星期數(1~7), 7表示星期日");
int number = scanner.nextInt();
switch (number) {
case 1:
String monday = "星期一";
System.out.println("今天是" + monday);
case 2:
String tuesday = "星期二";
System.out.println("今天是" + tuesday);
case 3:
String wednesday = "星期三";
System.out.println("今天是" + wednesday);
case 4:
String thursday = "星期四";
System.out.println("今天是" + thursday);
case 5:
String friday = "星期五";
System.out.println("今天是" + friday);
case 6:
String saturday = "星期六";
System.out.println("今天是" + saturday);
case 7:
String sunday = "星期日";
System.out.println("今天是" + sunday);
default:
System.out.println("無效日期");
}
}
}
運行結果:
很明顯,輸入數字3的時候,由於沒有break
,當執行case 3
內部代碼以後,它會向下執行其他case
中的代碼,直至default
內的代碼執行完畢為止。並且這段代碼還有可以進一步修改的空間,以下是加入break
併進行簡化的代碼:
import java.util.Scanner;
/**
* switch語句--添加break--穿透性
*
* @author iCode504
* @date 2023-11-15
*/
public class SwitchDemo2 {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println("請輸入星期數(1~7), 7表示星期日");
int number = scanner.nextInt();
String weekday;
switch (number) {
case 1:
weekday = "星期一";
break;
case 2:
weekday = "星期二";
break;
case 3:
weekday = "星期三";
break;
case 4:
weekday = "星期四";
break;
case 5:
weekday = "星期五";
break;
case 6:
weekday = "星期六";
break;
case 7:
weekday = "星期日";
break;
default:
weekday = "無效星期";
}
System.out.println("今天是" + weekday);
}
}
運行結果:
從上述結果可以看出,使用break
以後,就可以阻斷switch
穿透性。
switch
語句執行流程如下圖所示(每個case
都帶上break
語句):
在瞭解了switch
語句的基礎上,我們再來講解一個switch
語句和if-else
語句結合使用的案例:
案例:輸入年份和月份,輸出格式如下:xxxx年xx月有xx天。
常識:1、3、5、7、8、10、12恆定是31天;4、6、9、11恆定為30天。這幾個月份我們可以利用switch
的穿透性替換掉多條件的else if
判斷。
需要額外考慮的是:2月份的天數需要考慮年份是閏年還是平年,閏年能被400整除,例如:2000年,1600年是閏年,1900年就不是閏年。此外,如果不能被100整除,而能被4整除的也是閏年,例如:2020,2016,2004,2008年都是閏年。
結合上述分析,我們可以使用代碼進一步復現:
import java.util.Scanner;
/**
* switch和if結合使用
*
* @author iCode504
* @date 2023-11-15
*/
public class SwitchDemo3 {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.print("請輸入年份: ");
int year = scanner.nextInt();
System.out.print("請輸入月份: ");
int month = scanner.nextInt();
int day = 0;
switch (month) {
// 利用switch的穿透性
case 1:
case 3:
case 5:
case 7:
case 8:
case 10:
case 12:
day = 31;
break;
case 4:
case 6:
case 9:
case 11:
day = 30;
break;
case 2:
// 2月份需要額外針對年份進行判斷
if (year % 400 == 0) {
day = 29;
} else if (year % 4 == 0 && year % 100 != 0) {
day = 28;
}
break;
default:
// 不在1-12月份內做出說明
System.out.println("無效的月份");
}
System.out.println(year + "年" + month + "月有" + day + "天");
}
}
運行結果:
以我個人的開發經驗來看,使用switch
語句的頻率要比使用if
語句要少很多,二者的執行效率基本上差不太多。
if
可以編寫更加靈活的條件表達式。比如:判斷某個整數在[10, 20]
區間內,此時使用if
條件表達式可以寫成if (number >= 10 && number <= 20)
,如果使用switch
解決此問題會讓代碼變得更加複雜(因為你要寫很多個case
進行比較)。
switch
更擅長特定類型的值進行比較。以上面根據某年某月求當前月份由多少天為例,事實上完全使用if
語句實現,只不過我們需要寫成:
使用前面案例對應的switch
代碼,和if
語句對比,個人覺得可讀性變高:
因此,使用if
語句還是switch
語句還是得根據具體的代碼場景而決定。
六、《阿裡巴巴Java開發手冊》關於條件判斷語句的相關規範
1. 【強制】在一個switch
塊內,每個case
要麼通過continue/break/return
等來終止,要麼註釋說明程式將繼續執行到哪一個case
為止;在一個switch
塊內,都必須包含一個default
語句並且放在最後,即使它什麼代碼也沒有。
說明:註意break
是退出switch
語句塊,而return
是退出方法體。
2. 【強制】當switch
括弧內的變數類型為String
並且此變數為外部參數時,必須先進行null
判斷。
反例:如下的代碼輸出內容是什麼?
public class SwitchString {
public static void main(String[] args) {
method(null);
}
public static void method(String param) {
switch (param) {
// 肯定不是進入這裡
case "sth":
System.out.println("it's sth");
break;
// 也不是進入這裡
case "null":
System.out.println("it's null");
break;
// 也不是進入這裡
default:
System.out.println("default");
}
}
}
3. 【強制】在if/else/for/while/do
語句中必須使用大括弧。
說明:即使只有一行代碼,禁止不採用大括弧的編碼方式:if (條件表達式) statements;
,上述代碼需改成如下格式:
if (條件表達式) {
statements;
}
4. 【推薦】表達異常的分支時,少用if-else
方式,這種方式可以改寫成:
if (condition) {
...
return obj;
}
// 接著寫 else 的業務邏輯代碼;
說明:如果非使用if()...else if()...else...
方式表達邏輯,避免後續代碼維護困難,請勿超過 3 層。
正例:超過 3 層的if-else
的邏輯判斷代碼可以使用衛語句、策略模式、狀態模式等來實現,其中衛語句示例如下(不瞭解衛語句是什麼的小伙伴可以參考這篇文章:點我查看):
public void findBoyfriend (Man man){
if (man.isUgly()) {
System.out.println("本姑娘是外貌協會的資深會員");
return;
}
if (man.isPoor()) {
System.out.println("貧賤夫妻百事哀");
return;
}
if (man.isBadTemper()) {
System.out.println("銀河有多遠,你就給我滾多遠");
return;
}
System.out.println("可以先交往一段時間看看");
}
5. 【推薦】避免採用取反邏輯運算符。
說明:取反邏輯不利於快速理解,並且取反邏輯寫法必然存在對應的正向邏輯寫法。
正例:使用if (x < 628)
來表達 x 小於 628。
反例:使用if (!(x >= 628))
來表達 x 小於 628。
七、知識點總結
流程式控制制之條件判斷知識點總結如下圖所示:
如需高清大圖,請點擊右側鏈接下載文件:點我下載