目錄
?文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-725794.html
一、JDK新特性
1.1Java Record
1.1.1Record的使用
1.1.2Instance Methods
1.1.3靜態(tài)方法 Static Method
1.1.4Record構(gòu)造方法
1.1.5Record與Lombok
1.1.6Record實(shí)現(xiàn)接口
1.1.7Local Record
1.1.8嵌套R(shí)ecord
1.1.9instanceof判斷Record類型
1.1.10總結(jié)
1.2Switch
1.2.1箭頭表達(dá)式
1.2.2yield返回值
1.2.3Java Record
1.3Text Block
1.3.1認(rèn)識(shí)文本塊
1.3.2字符串比較與方法
1.3.3空白
1.3.4文本塊的方法
1.3.5轉(zhuǎn)義字符
1.3.6總結(jié)
1.4var
1.4.1var聲明局部變量
1.4.2什么時(shí)候使用var
1.5sealed
1.5.1Sealed Classes
1.5.2Sealed Interface
?
一、JDK新特性
-
JDK8-19新增了不少新特性,這里我們把實(shí)際常用的新特性進(jìn)行介紹。
-
Java Record
-
Switch 開(kāi)關(guān)表達(dá)式
-
Text Block 文本塊
-
var 聲明局部變量
-
sealed 密封類
-
1.1Java Record
-
Java14中預(yù)覽的新特性叫做Record,在Java中,Record是一種特殊類型的Java類??捎脕?lái)創(chuàng)建不可變類,語(yǔ)法簡(jiǎn)短。
-
任何時(shí)候創(chuàng)建Java類,都會(huì)創(chuàng)建大量的樣板代碼,如:
-
每個(gè)字段的set、get方法
-
公共的構(gòu)造方法
-
重寫hashCode()、toString()、equals()方法
-
-
使用Java Record避免上述的樣板代碼,如下特點(diǎn):
-
帶有全部參數(shù)的構(gòu)造方法
-
public訪問(wèn)器
-
toString()、hashCode()、equals()
-
無(wú)set、get方法,沒(méi)有遵循Bean的命名規(guī)范
-
final類,不能繼承Record,Record為隱式的final類,除此之外與普通類一樣
-
不可變類,通過(guò)構(gòu)造創(chuàng)建Record
-
final屬性不可修改
-
不能聲明實(shí)例屬性,能聲明static成員
-
1.1.1Record的使用
-
IDEA新建Class,選擇類Record
1.創(chuàng)建 Student Record
public record Student(Integer id, String name, String email, Integer age) {
}
2.創(chuàng)建 Record對(duì)象
@Test
public void test01() {
? ?//創(chuàng)建Record對(duì)象
? ?Student student = new Student(1001, "張三", "zhangsan@qq.com", 20);
? ?System.out.println(student);
?
? ?//public訪問(wèn)器獲取屬性值,只讀,沒(méi)有set、get方法
? ?Integer id = student.id();
? ?String name = student.name();
? ?System.out.println("id=" + id);
? ?System.out.println("name=" + name);
?
? ?Student student1 = new Student(1002, "李四", "lisi@qq.com", 21);
? ?System.out.println(student1);
?
? ?System.out.println("student1.equals(student)="+student1.equals(student));
?
? ?System.out.println(student1.name());
? ?System.out.println(student1.id());
}
?
3.查看控制臺(tái)輸出結(jié)果
?
-
Record 通過(guò)構(gòu)造方法創(chuàng)建了只讀對(duì)象,能夠讀取每個(gè)屬性,不能設(shè)置新的屬性值。
-
Record 用于創(chuàng)建不可變的對(duì)象,同時(shí)減少了樣板代碼。
-
Record 對(duì)每個(gè)屬性提供了public訪問(wèn)器,例如student.name()
1.1.2Instance Methods
-
Record是Java類,和普通Java類一樣定義方法。
1.創(chuàng)建實(shí)例方法
//實(shí)例方法,concat連接字符串
public String concat() {
return String.format("姓名是%s,年齡是%d", this.name, this.age);
}
2.調(diào)用實(shí)例方法
@Test
public void test2() {
? ?Student student = new Student(1001, "張三", "zhangsan@qq.com", 20);
? ?//使用對(duì)象,調(diào)用實(shí)例方法
? ?System.out.println(student.concat());
}
1.1.3靜態(tài)方法 Static Method
-
Record類定義靜態(tài)方法,和普通類一樣。
1.創(chuàng)建靜態(tài)方法
//靜態(tài)方法,把email轉(zhuǎn)為大寫
public static String emailToUpperCase(String email) {
? ?return Optional.ofNullable(email).orElse("no email").toUpperCase();
}
2.測(cè)試靜態(tài)方法
@Test
public void test3() {
? ?//使用類,調(diào)用靜態(tài)方法
? ?String email = Student.emailToUpperCase("zhangsan@qq.com");
? ?System.out.println(email);
}
1.1.4Record構(gòu)造方法
-
我們可以在Record中添加構(gòu)造方法,有三種類型的構(gòu)造方法:
-
緊湊型構(gòu)造方法:沒(méi)有任何參數(shù),甚至沒(méi)有括號(hào)
-
規(guī)范構(gòu)造方法:以所有成員作為參數(shù)
-
定制構(gòu)造方法:自定義參數(shù)個(gè)數(shù)
-
1.緊湊和定制構(gòu)造方法
//緊湊構(gòu)造方法
public Student {
? ?System.out.println("id=" + id);
? ?if (id < 1000) {
? ? ? ?throw new RuntimeException("id<1000");
? }
}
?
//自定義構(gòu)造方法
public Student(Integer id, String name) {
? ?this(id, name, null, null);
}
2.編譯Student.java->Student.class
/*緊湊構(gòu)造方法和規(guī)范構(gòu)造方法合并了*/
public Student(Integer id, String name, String email, Integer age) {
? ? ? ?System.out.println("id=" + id);
? ? ? ?if (id < 1000) {
? ? ? ? ? ?throw new RuntimeException("id<1000");
? ? ? } else {
? ? ? ? ? ?this.id = id;
? ? ? ? ? ?this.name = name;
? ? ? ? ? ?this.email = email;
? ? ? ? ? ?this.age = age;
? ? ? }
? }
?
? ?public Student(Integer id, String name) {
? ? ? ?this(id, name, (String)null, (Integer)null);
? }
3.測(cè)試
@Test
public void test4() {
? ?Student student = new Student(1001, "張三");
? ?System.out.println(student);
}
1.1.5Record與Lombok
-
Java Record是創(chuàng)建不可變類且減少樣板代碼的好方法,Lombok是一種減少樣板代碼的工具。
-
Lombok提供語(yǔ)法的便利性,通常預(yù)裝一些代碼模板,根據(jù)您加入到類中的注解自動(dòng)執(zhí)行代碼模板。這樣的庫(kù)純粹是為了方便實(shí)現(xiàn)POJO類,通過(guò)預(yù)編譯代碼,將代碼的模板加到class中。
-
Java Record是語(yǔ)言級(jí)別的,一種語(yǔ)義特性。為了建模而用,數(shù)據(jù)聚合。簡(jiǎn)單說(shuō)就是提供了通用的數(shù)據(jù)類,充當(dāng)“數(shù)據(jù)載體”,用于在類和應(yīng)用程序之間進(jìn)行數(shù)據(jù)傳輸。
1.1.6Record實(shí)現(xiàn)接口
-
Java Record可以與普通類一樣實(shí)現(xiàn)接口,重寫接口的方法。
1.創(chuàng)建新的接口,定義一個(gè)規(guī)范方法
public interface Print {
? ?void print();
}
2.創(chuàng)建新的Record實(shí)現(xiàn)接口,重寫接口的方法,實(shí)現(xiàn)當(dāng)前Record有關(guān)的業(yè)務(wù)邏輯
public record ProductRecord(Integer id, String name, Integer qty) implements Print {
? ?@Override
? ?public void print() {
? ? ? ?StringJoiner joiner = new StringJoiner("-");
? ? ? ?String s = joiner.add(id.toString()).add(name).add(qty.toString()).toString();
? ? ? ?System.out.println("商品信息:" + s);
? }
}
3.測(cè)試print方法
@Test
public void test5() {
? ?ProductRecord productRecord = new ProductRecord(1001, "電腦", 1000);
? ?productRecord.print();
}
1.1.7Local Record
-
Record 可以作為局部對(duì)象使用,在代碼塊中定義并使用Record。
定義Local Record
@Test
public void test6() {
? ?//定義local record
? ?record SaleRecord(String saleId, String productName, Double money) {}
? ?//創(chuàng)建對(duì)象
? ?SaleRecord saleRecord = new SaleRecord("001", "顯示器", 3000.00);
?
? ?System.out.println("saleRecord=" + saleRecord);
}
1.1.8嵌套R(shí)ecord
-
多個(gè)Record可以組合定義,一個(gè)Record能夠包含其他得到Record。
1.定義Record
public record Address(String city,String address,String zipcode) {}
public record Phone(String areaCode,String number) {}
public record Customer(String id, String name, Address address, Phone phone) {}
2.創(chuàng)建Customer對(duì)象并測(cè)試
@Test
public void test7() {
? ?Address address = new Address("鄭州", "新密", "452370");
? ?Phone phone = new Phone("0371", "60281234");
? ?Customer customer = new Customer("1001", "張三", address, phone);
? ?System.out.println(customer);
? ?System.out.println(customer.address().address());
? ?System.out.println(customer.phone().number());
}
1.1.9instanceof判斷Record類型
-
instance能夠與Java Record一起使用,編譯器知道記錄組件的確切數(shù)量和類型。
-
instanceof是Java的一個(gè)保留關(guān)鍵字,左邊是對(duì)象,右邊是類,返回類型是Boolean類型。
-
instanceof是測(cè)試左邊的對(duì)象是否是右邊類或者該類的子類創(chuàng)建的實(shí)例對(duì)象,是返回true,否返回false。
1.聲明Person Record,擁有兩個(gè)屬性name和age
public record Person(String name, Integer age) {}
2.在一個(gè)業(yè)務(wù)方法判斷當(dāng)是Record類型時(shí),繼續(xù)判斷age年齡是否滿足18歲
public class SomeService {
? ?//定義業(yè)務(wù)方法,判斷年齡是否18
? ?public boolean isEligible(Object obj) {
? ? ? ?/*if (obj instanceof Person(String name,Integer age)) {
? ? ? ? ? ?return age >= 18;
? ? ? ?}*/
? ? ? ?if (obj instanceof Person(String name,Integer age) p) {
? ? ? ? ? ?return p.age() >= 18;
? ? ? }
? ? ? ?return false;
? }
}
3.測(cè)試
@Test
public void test8() {
? ?Person person = new Person("李四", 20);
? ?SomeService someService = new SomeService();
? ?boolean flag = someService.isEligible(person);
? ?System.out.println(flag);
}
1.1.10總結(jié)
-
java.lang.Class類與Record類有關(guān)的兩個(gè)方法
-
判斷一個(gè)類是否是Record類型:
boolean isRecord()
-
Record的數(shù)組,表示此記錄類的所有記錄組件:
RecordComponent[] getRecordComponents()
-
//判斷Customer是否為Java Record類型
boolean record = customer.getClass().isRecord();
System.out.println("record=" + record);
?
RecordComponent[] recordComponents = customer.getClass().getRecordComponents();
for (RecordComponent recordComponent : recordComponents) {
? ?System.out.println("recordComponent=" + recordComponent);
}
1.2Switch
-
Switch特點(diǎn):
-
支持箭頭表達(dá)式
-
支持yield返回值
-
支持Java Record
-
1.2.1箭頭表達(dá)式
@Test
public void test01() {
? ?int week = 7;
? ?String memo = "";//表示計(jì)算結(jié)果
? ?switch (week) {
? ? ? ?case 1 -> memo = "星期日,休息";
? ? ? ?case 2, 3, 4, 5, 6 -> memo = "工作日";
? ? ? ?case 7 -> memo = "星期六,休息";
? ? ? ?default -> throw new RuntimeException("無(wú)效的日期");
? }
? ?System.out.println("memo=" + memo);
}
1.2.2yield返回值
-
yield讓switch作為表達(dá)式,能夠返回值。
-
無(wú)需中間變量,switch作為表達(dá)式計(jì)算,可以得到結(jié)果,yield是表達(dá)式的返回值。
@Test
public void test02() {
? ?int week = 10;
? ?String memo = switch (week) {
? ? ? ?case 1:
? ? ? ? ? ?yield "周日";
? ? ? ?case 2, 3, 4, 5, 6:
? ? ? ? ? ?yield "工作日";
? ? ? ?case 7:
? ? ? ? ? ?yield "周六";
? ? ? ?default:
? ? ? ? ? ?yield "無(wú)效日期";
? };
? ?System.out.println("week = " + memo);
}
-
多表達(dá)式,case與yield結(jié)合使用
@Test
? ?public void test03() {
? ? ? ?int week = 7;
? ? ? ?String memo = switch (week) {
? ? ? ? ? ?case 1 -> {
? ? ? ? ? ? ? ?System.out.println("周日,執(zhí)行了代碼塊");
? ? ? ? ? ? ? ?yield "周日";
? ? ? ? ? }
? ? ? ? ? ?case 2, 3, 4, 5, 6 -> {
? ? ? ? ? ? ? ?System.out.println("工作日,執(zhí)行了代碼塊");
? ? ? ? ? ? ? ?yield "工作日";
? ? ? ? ? }
? ? ? ? ? ?case 7 -> "周六";
? ? ? ? ? ?default -> {
? ? ? ? ? ? ? ?System.out.println("其它");
? ? ? ? ? ? ? ?throw new RuntimeException("無(wú)效日期");
? ? ? ? ? }
? ? ? };
? ? ? ?System.out.println("week=" + memo);
? }
-
提示
-
case -> 不能與 case : 混用,一個(gè)switch語(yǔ)句塊中使用一種語(yǔ)法格式。
-
1.2.3Java Record
-
switch表達(dá)式中使用record,結(jié)合case -> 表達(dá)式 ,yield實(shí)現(xiàn)復(fù)雜的計(jì)算。
1.準(zhǔn)備三個(gè)Record
public record Line(int x, int y) {}
public record Circle(int r) {}
public record Rectangle(int width, int height) {}
2.switch record
@Test
public void test04() {
? ?Circle circle = new Circle(10);
? ?Line line = new Line(10, 20);
? ?Rectangle rectangle = new Rectangle(10, 20);
?
? ?Object obj = circle;
? ?int res = switch (obj) {
? ? ? ?case Circle(int r) -> {
? ? ? ? ? ?System.out.println("圓的半徑為:" + r);
? ? ? ? ? ?yield 3 * r * r;
? ? ? }
? ? ? ?case Line(int x,int y) -> {
? ? ? ? ? ?System.out.println("線段的長(zhǎng)度為:" + (y - x));
? ? ? ? ? ?yield y - x;
? ? ? }
? ? ? ?case Rectangle(int w,int h) -> w * h;
? ? ? ?default -> 0;
? };
? ?System.out.println("res=" + res);
}
1.3Text Block
-
Text Bolck處理多行文本十分方便,無(wú)需連接“+”單引號(hào)、換行符等。
1.3.1認(rèn)識(shí)文本塊
-
語(yǔ)法:使用三個(gè)雙引號(hào)括起來(lái)的字符串。
"""
內(nèi)容
"""
-
例如:
String name = """lisi"""; //Error 不能將文本塊放在單行上 String name= """lisi 20"""; //Error 文本塊的內(nèi)容不能在沒(méi)有中間行結(jié)束符的情況下跟隨三個(gè)開(kāi)頭雙引號(hào) String myname= """ zhangsan 20 """; //正確 String s1 = """ ? ?張三""";//正確
1.3.2字符串比較與方法
-
三個(gè)雙引號(hào)字符""" 與兩個(gè)雙引號(hào)""的字符串處理是一樣的,與普通字符串一樣使用。例如 equals(),"==",連接字符串("+"),作為方法的參數(shù)等。
@Test
public void fun1() {
? ? ? ?String s1 = """
? ? ? ? ? ? ? ?lisi
? ? ? ? ? ? ? ?""";
? ? ? ?String s2 = """
? ? ? ? ? ? ? ?lisi
? ? ? ? ? ? ? ?""";
//比較字符串
? ? ? ?boolean b1 = s1.equals(s2);
? ? ? ?System.out.println("b1 = " + b1);
//使用 == 的比較
? ? ? ?boolean b2 = s1 == s2;
? ? ? ?System.out.println("b2 = " + b2);
? ? ? ?String msg = """
? ? ? ? ? ? ? ?hello world""";
//字符串方法 substring
? ? ? ?String sub = msg.substring(0, 5);
? ? ? ?System.out.println("sub = " + sub);
? }
1.3.3空白
示例:
@Test
public void test02() {
? ?//按tab鍵向右移動(dòng),保留左側(cè)空格
? ?String msg = """
? ? ? ? ? ? ? ?<html>
? ? ? ? ? ? ? ? ? ?<body>張三</body>
? ? ? ? ? ? ? ?</html>
? ? ? ? ? ?""";
? ?System.out.println(msg);
?
? ?String colors = """
? ? ? ? ? ?blue
? ? ? ? ? ?red
? ? ? ? ? ?green
? ? ? ? ? ?""";
? ?//indent(int space) 包含縮進(jìn),space為空格的數(shù)量
? ?colors = colors.indent(10);
? ?System.out.println(colors);
}
輸出
1.3.4文本塊的方法
-
Text Block的格式方法 formatted()
@Test
public void test03() {
? ?String info= """
? ? ? ? ? ? ? Name:%s
? ? ? ? ? ?\nPhone:%s
? ? ? ? ? ?Age:%d
? ? ? ? ? ?""".formatted("張三","123",23);
? ?System.out.println(info.translateEscapes().strip());
}
-
String strip():刪除每行開(kāi)頭和結(jié)尾的空白
-
String translateEscapes():轉(zhuǎn)義序列轉(zhuǎn)換為字符串字面量
1.3.5轉(zhuǎn)義字符
@Test
public void test04() {
? ?String str= """
? ? ? ? ? ?Spring Boot 是一個(gè)快速開(kāi)發(fā)框架 \
? ? ? ? ? ?基于\"Spring\"框架,創(chuàng)建 Spring 應(yīng)用 \
? ? ? ? ? ?內(nèi)嵌 Web 服務(wù)器,以 jar 或 war 方式運(yùn)行 \
? ? ? ? ? ?""";
? ?System.out.println(str);
}
1.3.6總結(jié)
-
多行字符串,應(yīng)該使用Text Block
-
當(dāng)Text Block可以提高代碼的清晰的時(shí),推薦使用。例如代碼中嵌入SQL語(yǔ)句。
-
避免不必要的縮進(jìn),開(kāi)頭和結(jié)尾部分。
-
空格和制表符不能混合使用。
-
對(duì)于大多數(shù)多行字符串, 分隔符位于上一行的右端,并將結(jié)束分隔符位于文本塊單獨(dú)行上。
1.4var
-
在JDK10及更高版本中,可以使用var標(biāo)識(shí)符聲明具有非空初始化式的局部變量,這可以幫助您編寫簡(jiǎn)潔的代碼,消除冗余信息使代碼更具有可讀性,謹(jǐn)慎使用。
1.4.1var聲明局部變量
-
var特點(diǎn)
-
var 是一個(gè)保留字,不是關(guān)鍵字(可以聲明var為變量名)
-
方法內(nèi)聲明的局部變量,必須有初始值,不能為空
-
每次聲明一個(gè)變量,不能復(fù)合聲明多個(gè)變量。
var s1="Hello", age=20; //Error
-
var 動(dòng)態(tài)類型是編譯器根據(jù)變量所賦的值來(lái)推斷類型
-
var代替顯示類型,代碼簡(jiǎn)潔,減少不必要的排版
-
-
var優(yōu)缺點(diǎn)
-
代碼簡(jiǎn)潔和整齊
-
降低了程序的可讀性
-
示例
//通常
try (Stream<Customer> result = dbconn.executeQuery(query)) {
//...
//推薦
try (var customers = dbconn.executeQuery(query)) {
//...
}
比較 Stream<Customer> result 與 var customers
1.4.2什么時(shí)候使用var
-
簡(jiǎn)單的臨時(shí)變量
-
復(fù)雜,多步驟邏輯,嵌套的表達(dá)式等,簡(jiǎn)短的變量有助于理解代碼
-
能夠確定變量的初始值
-
變量類型比較長(zhǎng)時(shí)
示例
public void fun1(){
var s1="lisi";
var age = 20;
for(var i=0;i<10;i++){
System.out.println("i = " + i);
}
List<String> strings = Arrays.asList("a", "b", "c");
for (var str: strings){
System.out.println("str = " + str);
}
1.5sealed
-
Sealed Classes 主要特點(diǎn)是限制繼承,Java中通過(guò)繼承增強(qiáng),擴(kuò)展了類的能力,復(fù)用某些功能。當(dāng)這種能力不受控,與原有類的設(shè)計(jì)相違背,導(dǎo)致不預(yù)見(jiàn)的異常邏輯。
-
Sealed 限制無(wú)限的擴(kuò)張。
-
Java種已有的sealed的設(shè)計(jì)
-
final關(guān)鍵字,修飾類不能被繼承
-
private限制私有類
-
-
sealed作為關(guān)鍵字可以在class和interface上使用,結(jié)合permits關(guān)鍵字。定義限制繼承的密封類。
1.5.1Sealed Classes
sealed class 類名 permits 子類1,子類2,... 列表{}
1.聲明sealed Class
public sealed class Shape permits Circle,Square,Rectangle{
? ?public void draw(){
? ? ? ?System.out.println("畫一個(gè)Shape");
? }
}
-
permits表示允許的子類,一個(gè)或多個(gè)
2.聲明子類
-
子類聲明的三種方式
-
final 終結(jié),依然是密封的
-
sealed 子類是密封的,需要子類實(shí)現(xiàn)
-
non-sealed 非密封類,擴(kuò)展使用,不受限
-
//第一種 final
public final class Circle extends Shape {
}
//第二種 sealed class
public sealed class Square extends Shape permits RoundSquare {
@Override
public void draw() {
System.out.println("=======Square 圖形======");
}
}
//密封類的子類的子類
public final class RoundSquare extends Square{
}
//非密封類 , 可以被擴(kuò)展。放棄密封
public non-sealed class Rectangle extends Shape {
}
//繼承非密封類
public class Line extends Rectangle{
}
1.5.2Sealed Interface
-
密封接口同密封類
1.聲明密封接口
public sealed interface SomeService permits SomeServiceImpl {
? ?void doSome();
}
2.實(shí)現(xiàn)接口
public final class SomeServiceImpl implements SomeService {
@Override
public void doSome() {
System.out.println("SomeServiceImpl");
}
}
?文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-725794.html
?
到了這里,關(guān)于[Java]JDK17新特性的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!