導(dǎo)讀
最近網(wǎng)上開始了大量的關(guān)于Java19的討論,我也想著用了Java8這么久該接受一點(diǎn)新的東西了,于是便開始研究了起來
Java 19
Java19是一個(gè)免費(fèi)版本海蔽。下面是JDK19的支持圖
(來源:https://www.bilibili.com/video/BV1V84y1B7dD?t=39.9)
可以看到目前較為長(zhǎng)期的免費(fèi)支持版本是Java17,而下一個(gè)版本是Java21(免費(fèi)支持于2027年結(jié)束)
開始研究
在網(wǎng)上查找了大量的文件并對(duì)JDK9-19做了些整理打算從以下幾個(gè)功能去了解從Java8-Java19的發(fā)展
- 數(shù)組轉(zhuǎn)列表和列表轉(zhuǎn)數(shù)組(Java 9)
- var關(guān)鍵字(Java 10)
- yield關(guān)鍵字(Java 13)
- Record(記錄)類(Java 14)
- case的多個(gè)值匹配(Java 14)
- case返回值(Java 14,17)
- Sealed(密閉)類(Java 15)
- switch類型判斷(Java 17)
- 文本塊(Java 17)
- switch復(fù)雜表達(dá)式(Java 19 第三次預(yù)覽(正式版Java 19該功能被移除狂塘,不排除以后會(huì)加入的可能))
數(shù)組轉(zhuǎn)列表和列表轉(zhuǎn)數(shù)組(Java 9)
@Test
public void test(){
String[] strings={"你好","早","這foe及","vdsoijfdois"};
List<String> stringList=List.of(strings);//JDK9
System.out.println(stringList);
}
List.of
為JDK9帶來的新功能,他可以將數(shù)組轉(zhuǎn)換為對(duì)應(yīng)的列表(List)鳄厌,但是荞胡,轉(zhuǎn)換后的List是不能改變的。
var關(guān)鍵字(Java 10)
var關(guān)鍵字可以不用顯式地聲明變量的類型了嚎。舉例:
public class People{
private String name;
private int age;
//Getter Setter...
}
public static void main(String[] args){
var people=new Student();
people.setSid("321321");
//...
}
雖說不會(huì)顯示地聲明類型泪漂,但實(shí)際上,變量的類型是確定的歪泳,因?yàn)椋?/p>
- 使用var聲明的變量必須被初始化
- 初始化時(shí)是什么類型以后再賦值時(shí)必須是這個(gè)類型或者這個(gè)類的子類
yield關(guān)鍵字(Java 13)
yield
目前貌似只適用于case分支中萝勤,舉例:
@Test
public void returedSwitch2(){
Scanner scanner=new Scanner(System.in);
int i = scanner.nextInt();
int result=switch (i){
case 1->{
System.out.printf("輸入的是%d",i);
yield i+3;
}
case 2->{
System.out.printf("輸入的是%d呀",i);
yield i-5;
}
default -> i;
};
System.out.printf("result=%d",result);
}
它的作用是將case分支中yield后面的值作為返回值返回回來。如果要使用yield關(guān)鍵字或者想讓switch返回一個(gè)值則case后面的:
必須被替換為->
呐伞。
->
這個(gè)符號(hào)在switch中的應(yīng)用是Java 12帶來的敌卓,它的作用是讓case的執(zhí)行唯一,直白說就是不會(huì)再“逢break土媲猓”趟径。
舉個(gè)例子:
Scanner scanner=new Scanner(System.in);
String next = scanner.next();
//part 1
String response=switch (next){
case "你好","早上好","中午好","下午好"->"你好呀";
case "我不是很好","我不好","我難受"->"不要傷心嘛";
default -> "需要幫助嗎?";
};
System.out.println(response);
System.out.println("與上面的對(duì)比");
//part 2
switch (next){
case "你好","早上好","中午好","下午好":
System.out.println("你好呀");
case "我不是很好","我不好","我難受":System.out.println("不要傷心嘛");break;
default :System.out.println("需要幫助嗎癣防?") ;break;
};
part 1就是新的switch語(yǔ)法蜗巧,它避免了大量的break出現(xiàn)在代碼中,如果case "你好","早上好","中午好","下午好"
滿足劣砍,則返回"你好呀"
惧蛹,而不像原來那樣把所有結(jié)果都返回。對(duì)于同一個(gè)需求刑枝,part1的寫法顯然比part2的寫法方便一些香嗓。
Record(記錄)類(Java 14)
record
關(guān)鍵字可以將某個(gè)類標(biāo)識(shí)為記錄類,被該關(guān)鍵字標(biāo)記的類會(huì)自動(dòng)生成Getter和Setter以及hashCode()
装畅,toString()
方法靠娱,同時(shí),該類的值不會(huì)再被改變掠兄!
舉例:
//Record類只能這么定義
public record StudentRecord(String id, String name, int age) {
}
@Test
public void recordClass(){
StudentRecord sr=new StudentRecord("123","張三",12);
System.out.println(sr);
System.out.printf("""
id:%s,姓名:%s
年齡:%d
""",sr.id(),sr.name(),sr.age());
}
這個(gè)類在前后端分離項(xiàng)目中是很有用的像云。
case的多個(gè)值匹配(Java 14)與case返回值(Java 14锌雀,17)
其實(shí)從Java 12開始就對(duì)switch進(jìn)行改動(dòng)了,在Java 14中迅诬,switch可以對(duì)多個(gè)值進(jìn)行比較了腋逆,相比于以前的case 1:case 2...這種簡(jiǎn)化了很多,在yield關(guān)鍵字章節(jié)使用的就是這個(gè)特性侈贷。
String response=switch (next){
case "你好","早上好","中午好","下午好"->"你好呀";
case "我不是很好","我不好","我難受"->"不要傷心嘛";
default -> "需要幫助嗎惩歉?";
};
下面的寫法也是正確的
switch (next){
case "你好","早上好","中午好","下午好":System.out.println("你好呀");
case "我不是很好","我不好","我難受":System.out.println("不要傷心嘛");
default :System.out.println( "需要幫助嗎?");
};
第一個(gè)寫法是可以將"你好呀"俏蛮、"不要傷心嘛"這類字符串作為switch返回值賦值給response的撑蚌。
第二個(gè)寫法則只能進(jìn)行多值匹配,switch沒辦法返回任何值搏屑,原因可以參見yield關(guān)鍵字章節(jié)
Sealed(密閉)類(Java 15)
有時(shí)候可能不希望某個(gè)接口或者類被某個(gè)類實(shí)現(xiàn)或者繼承争涌,那么,密閉類就可以滿足這個(gè)要求辣恋。
public sealed interface AnimalMethods permits Animal{
public void call();
}
public sealed class Animal implements AnimalMethods permits Sheep,Cow{
private String name;
private int age;
private Date birthDate;
//Getter,Setter...
@Override
public void call() {
System.out.println("任何動(dòng)物都有叫聲");
}
}
public non-sealed class Sheep extends Animal{
@Override
public void call() {
System.out.println("咩~");
}
}
public non-sealed class Cow extends Animal{
@Override
public void call() {
System.out.println("牟~");
}
}
首先我定義了一個(gè)密閉接口AnimalMethods
并限制只能讓Animal類或者接口來實(shí)現(xiàn)或者繼承它亮垫。
然后創(chuàng)建一個(gè)類Animal
實(shí)現(xiàn)接口AnimalMethods
,同時(shí)Animal
類也是一個(gè)密閉類抑党,要求只有Sheep
類和Cow
類可以繼承這個(gè)類包警。
最后創(chuàng)建Sheep
和Cow
類。
密閉類有這樣的性質(zhì):
- seald關(guān)鍵字不能和final以及record關(guān)鍵字一起使用
- seald關(guān)鍵字必須和permits關(guān)鍵字一起使用
- 密閉類必須有子類且必須限制所有子類底靠,密閉接口必須有子接口或者實(shí)現(xiàn)類并且限制所有子接口以及實(shí)現(xiàn)類。
以上面的代碼為例特铝,將public sealed class Animal implements AnimalMethods permits Sheep,Cow
改為public sealed class Animal implements AnimalMethods permits Sheep
同時(shí)保持繼承關(guān)系不變暑中,那么會(huì)編譯失敗,因?yàn)椋?code>Cow類也是Animal
類的子類鲫剿,因此permites
也必須包含Cow
類 - 使用seald標(biāo)記的類或接口其子類或子接口必須是
seald
鳄逾、non-seald
(非密閉)、final
中的一種
switch類型判斷(Java 17)
switch可以代替instanceof
關(guān)鍵字對(duì)對(duì)象的類型進(jìn)行判斷灵莲。
需要注意的是雕凹,在Java 19正式版中并不支持這個(gè)功能。
Object number=new Student();
//這個(gè)功能目前在孵化中
var result=switch (number){
case null-> "啊哦";
case Integer i->"int";
case Student s->"Student";
default -> "Oops";
};
System.out.println(result);
這確實(shí)是一個(gè)很大的改進(jìn)政冻,希望以后可以實(shí)裝
文本塊(Java 17)
在Record(記錄)類(Java 14)章節(jié)可以看到文本塊的影子枚抵,使用"""
(3個(gè)英文雙引號(hào))就可以定義一個(gè)文本塊。它的目的是為了解決“使用+
鏈接帶有轉(zhuǎn)義字符的字符串導(dǎo)致的代碼難看的問題明场∑。”
在以前,想要輸出含有轉(zhuǎn)義字符的字符串同時(shí)還要方便代碼編寫是不可能的苦锨,只能通過+
完成逼泣,比如:
public static void main(String[] args){
System.out.printf("姓名:%s"+
"性別:%c"+
"年齡:%d","張三",'m',18);
}
很痛苦趴泌,這樣寫代碼很難看,有了文本塊后就可以這么寫:
public static void main(String[] args){
System.out.printf("""
姓名:%s
性別:%c
年齡:%d
""","張三",'m',18);
}
方便了很多拉庶,而且代碼也不是很難看嗜憔。
(你問我printf
是新功能嗎?——不是J险獭)
switch復(fù)雜表達(dá)式(Java 19 第三次預(yù)覽(正式版Java 19該功能被移除痹筛,不排除以后會(huì)加入的可能))
你是否被大量的if-else所困擾?現(xiàn)在廓鞠,解決方案來了帚稠,你可以使用switch進(jìn)行表達(dá)式的判斷了。
Student student=new Student();
student.setAge(12);
String result= switch (student){
case Student s when s.getAge()>=18->"已成年";
default -> "未成年";
};
System.out.println(result);
Student student=new Student();
student.setAge(12);
if(student.getAge>=18){
System.out.println("已成年");
else{
System.out.println("未成年");
}
這個(gè)例子很簡(jiǎn)單床佳,如果你要進(jìn)行多種判斷的話無疑這種寫法是最方便的也更整潔滋早。
但是,在正式的Java19中不支持這個(gè)功能砌们。
評(píng)價(jià)
以上只是介紹了這些新特性的一小部分杆麸,實(shí)際上,這幾個(gè)版本都對(duì)性能浪感、開發(fā)復(fù)雜程度做了一定的優(yōu)化昔头。同時(shí),也讓Java的開發(fā)變得簡(jiǎn)單了一些影兽。
關(guān)于市場(chǎng):由于目前國(guó)內(nèi)大部分的公司所開發(fā)的項(xiàng)目使用的還是Java 8揭斧。因此,市場(chǎng)上在相當(dāng)長(zhǎng)的一段時(shí)間內(nèi)還是會(huì)青睞Java 8峻堰。所以對(duì)于小白而言還是以Java 8的學(xué)習(xí)為主讹开,高版本的Java感興趣的話可以自己去了解。
對(duì)于框架:Springboot 3已經(jīng)明確要求使用Java 17以上捐名,因此旦万,在不久的將來,如果依然使用Springboot開發(fā)的話那么Java 8會(huì)被淘汰掉镶蹋。由于Java 19剛剛發(fā)布不久成艘,很多框架(如Mybatis-plus)還沒有做支持,所以贺归,最近不要使用Java19+Springboot做一些項(xiàng)目淆两,過一段時(shí)間之后再看看。