動(dòng)力節(jié)點(diǎn)springboot3視頻筆記第一章
1.JDK關(guān)注的新特性
1.1 搭建學(xué)習(xí)環(huán)境
JDK:JDK19OpenJDK: https://jdk.java.net/19/Liberica JDK: https://bell-sw.com/pages/downloads/, 是一個(gè)OpenJDK發(fā)行版,為云原生弓柱,容器特別優(yōu)化记舆。
Maven:構(gòu)建和依賴(lài)管理灭忠,版本選擇3.6以上配置本地倉(cāng)庫(kù)和阿里云鏡像
IDEA2022.3.1Ultimate:主要的開(kāi)發(fā)工具,我是30天試用版本
數(shù)據(jù)庫(kù):MySQL 5以上版本
火狐瀏覽器:版本用比較新的舌狗,中文版本葡兑。
文本工具:EditPlus, Sublime任意。
1.2 有用的新特性
JDK8-19新增了不少新特性,這里我們把實(shí)際常用的新特性衫贬,給大家介紹一下。包括以下幾個(gè)方面:
[if !supportLists]1.?[endif]Java Record
[if !supportLists]2.?[endif]Swich開(kāi)關(guān)表達(dá)式
[if !supportLists]3.?[endif]Text Block文本塊
[if !supportLists]4.?[endif]var 聲明局部變量
[if !supportLists]5.?[endif]sealed 密封類(lèi)
1.2.1 Java Record
Java14中預(yù)覽的新特性叫做Record歇攻,在Java中固惯,Record是一種特殊類(lèi)型的Java類(lèi)〗墒兀可用來(lái)創(chuàng)建不可變類(lèi)葬毫,語(yǔ)法簡(jiǎn)短。參考JEP 395.?Jackson 2.12支持Record類(lèi)屡穗。
任何時(shí)候創(chuàng)建Java類(lèi)供常,都會(huì)創(chuàng)建大量的樣板代碼,我們可能做如下:
[if !supportLists]·?[endif]每個(gè)字段的set鸡捐,get方法
[if !supportLists]·?[endif]公共的構(gòu)造方法
[if !supportLists]·?[endif]重寫(xiě)hashCode, toString(), equals()方法
Java Record避免上述的樣板代碼栈暇,如下特點(diǎn):
[if !supportLists]·?[endif]帶有全部參數(shù)的構(gòu)造方法
[if !supportLists]·?[endif]public訪問(wèn)器
[if !supportLists]·?[endif]toString(),hashCode(),equals()
[if !supportLists]·?[endif]無(wú)set,get方法箍镜。沒(méi)有遵循Bean的命名規(guī)范
[if !supportLists]·?[endif]final類(lèi)源祈,不能繼承Record,Record為隱士的final類(lèi)色迂。除此之外與普通類(lèi)一樣
[if !supportLists]·?[endif]不可變類(lèi)香缺,通過(guò)構(gòu)造創(chuàng)建Record
[if !supportLists]·?[endif]final屬性,不可修改
[if !supportLists]·?[endif]不能聲明實(shí)例屬性歇僧,能聲明static成員
IDEA創(chuàng)建新的Maven工程 Lession01-feature
1.2.1.1 看看Record怎么用
IDEA新建Class图张,選擇類(lèi)Record
step1: 創(chuàng)建Student Recordpublic record Student(Integer id,String name,String email,Integer age) {}
step2:創(chuàng)建Record對(duì)象
public static void main(String[] args) {Student lisi = new Student(1001, "lisi","lisi@qq.com",20); ???System.out.println("lisi = " + lisi.toString());Student zhangsan = new Student(1002, "zhangsan","lisi@qq.com",20); ???System.out.println("zhangsan = " + zhangsan.toString()); ???System.out.println("lisi.equals(zhangsan) = " + lisi.equals(zhangsan)); ???System.out.println("lisi.name() = " + lisi.name()); ???System.out.println("zhangsan.name() = " + zhangsan.name());}
現(xiàn)在能查看控制臺(tái)輸出:lisi = Student[id=1001, name=lisi,email=lisi@qq.com, age=20]zhangsan = Student[id=1002, name=zhangsan, email=lisi@qq.com, age=20]lisi.equals(zhangsan) = falselisi.name() = lisizhangsan.name() = zhangsan
Record通過(guò)構(gòu)造方法創(chuàng)建了只讀的對(duì)象,能夠讀取每個(gè)屬性诈悍,不能設(shè)置新的屬性值祸轮。 Record用于創(chuàng)建不可變的對(duì)象,同時(shí)減少了樣板代碼侥钳。Record對(duì)每個(gè)屬性提供了public訪問(wèn)器适袜,例如lisi.name()
1.2.1.2 Instance Methods
Record是Java類(lèi),和普通Java類(lèi)一樣定義方法舷夺。下面定義方法concat苦酱,將姓名和年齡一起打印輸出。我們創(chuàng)建普通的方法concat给猾,將name和age連接為一個(gè)字符串輸出疫萤。
step1:創(chuàng)建實(shí)例方法
public record Student(Integer id,String name,String email,Integer age) {public String concat(){return String.format("姓名:%s,年齡是:%d", this.name,this.age);}}
step2: 調(diào)用實(shí)例方法
public static void main(String[] args) {Student lisi = new Student(1001, "lisi","lisi@qq.com",20);String nameAndAge = lisi.concat();System.out.println( nameAndAge);}
最后控制臺(tái)輸出:姓名:lisi敢伸,年齡是:20
1.2.1.3 靜態(tài)方法 Static Method
Record類(lèi)定義靜態(tài)方法扯饶,試用靜態(tài)方法與普通類(lèi)一樣。step1: 創(chuàng)建靜態(tài)方法
public record Student(Integer id,String name,String email,Integer age) {public String concat(){return String.format("姓名:%s,年齡是:%d", this.name,this.age);}/** ?靜態(tài)方法 ?*/public static String emailUpperCase(String email){return Optional.ofNullable(email).orElse("no email").toUpperCase();}}
step2:測(cè)試靜態(tài)方法
public static void main(String[] args) {????String emailUpperCase = Student.emailUpperCase("lisi@163.com"); ???????System.out.println("emailUpperCase = " + emailUpperCase);????}
1.2.1.4 Record的構(gòu)造方法
我們可以在Record中添加構(gòu)造方法帝际, 有三種類(lèi)型的構(gòu)造方法分別:是緊湊的,規(guī)范的和定制構(gòu)造方法v緊湊型構(gòu)造方法沒(méi)有任何參數(shù)饶辙,甚至沒(méi)有括號(hào)蹲诀。v規(guī)范構(gòu)造方法是以所有成員作為參數(shù)v定制構(gòu)造方法是自定義參數(shù)個(gè)數(shù)
step1: 緊湊和定制構(gòu)造方法
public record Student(Integer id,String name,String email,Integer age) {/緊湊構(gòu)造方法/public Student {System.out.println("id"+ id );if( id < 1 ){throw new RuntimeException("ok");}}/自定義構(gòu)造方法/public Student(Integer id, String name) {this(id, name, null, null);}}
step2:編譯Student.java -> Student.class
public record Student(Integer id, String name, String email, Integer age) {/** 緊湊構(gòu)造方法和規(guī)范構(gòu)造方法合并了 */public Student(Integer id, String name, String email, Integer age) {System.out.println("id" + id);if (id < 1) {throw new RuntimeException("ok"); ???}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);}}
1.2.1.5 Record與Lombok
Java Record是創(chuàng)建不可變類(lèi)且減少樣板代碼的好方法。Lombok是一種減少樣板代碼的工具弃揽。兩者有表面上的重疊部分脯爪。可能有人會(huì)說(shuō)Java Record會(huì)代替Lombok. 兩者是有不同用途的工具矿微。Lombok提供語(yǔ)法的便利性痕慢,通常預(yù)裝一些代碼模板,根據(jù)您加入到類(lèi)中的注解自動(dòng)執(zhí)行代碼模板涌矢。這樣的庫(kù)純粹是為了方便實(shí)現(xiàn)POJO類(lèi)掖举。通過(guò)預(yù)編譯代碼。將代碼的模板加入到class中娜庇。Java Record是語(yǔ)言級(jí)別的塔次,一種語(yǔ)義特性,為了建模而用名秀,數(shù)據(jù)聚合励负。簡(jiǎn)單說(shuō)就是提供了通用的數(shù)據(jù)類(lèi),充當(dāng)“數(shù)據(jù)載體"匕得,用于在類(lèi)和應(yīng)用程序之間進(jìn)行數(shù)據(jù)傳輸继榆。
1.2.1.6 Record實(shí)現(xiàn)接口
Java Record可以與普通類(lèi)一樣實(shí)現(xiàn)接口,重寫(xiě)接口的方法汁掠。
step1: 創(chuàng)建新的接口略吨,定義一個(gè)規(guī)范方法。
public interface PrintInterface {/** 輸出自定義描述信息 */void print();}
step2: 創(chuàng)建新的Record實(shí)現(xiàn)接口考阱,重寫(xiě)接口的方法晋南,實(shí)現(xiàn)當(dāng)前Record有關(guān)的業(yè)務(wù)邏輯
public record ProductRecord(String id,String name,Integer qty)implements PrintInterface {@Override ?public void print() {String productDesc = String.join("-", id, name, qty.toString()); ????System.out.println("商品信息 = " + productDesc);}}ProductRecord實(shí)現(xiàn)print()方法,打印商品詳情羔砾。
step3:測(cè)試print方法
public static void main(String[] args) {ProductRecord product = new ProductRecord("P001", "手機(jī)", 100);product.print();}
1.2.1.7 Local Record
Record可以作為局部對(duì)象使用负间。在代碼塊中定義并使用Record,下面定義一個(gè)SaleRecord
step1:定義Local Record
public static void main(String[] args) {//定義Java Recordrecord SaleRecord(String saleId,String productName,Double money){};//創(chuàng)建Local RecordSaleRecord saleRecord = new SaleRecord("S22020301", "手機(jī)", 3000.0);//使用SaleRecordSystem.out.println("銷(xiāo)售記錄 = " + saleRecord.toString());}
控制臺(tái)輸出:銷(xiāo)售記錄= SaleRecord[saleId=S22020301, productName=手機(jī), money=3000.0]
1.2.1.8 嵌套R(shí)ecord
多個(gè)Record可以組合定義姜凄, 一個(gè)Record能夠包含其他的Record政溃。我們定義Record為Customer,存儲(chǔ)客戶(hù)信息态秧,包含了Address和PhoneNumber兩個(gè)Record
step1:定義Record
public record Address(String city,String address,String zipcode) {????}public record PhoneNumber(String areaCode,String number) {????}public record Customer(String id, ?String name, ?PhoneNumber phoneNumber, ??????????????????????Address address) {????}
step2: 創(chuàng)建Customer對(duì)象
public static void main(String[] args) {Address address = new Address("北京", "大興區(qū)涼水河二街-8號(hào)10棟三層", "100176"); ???PhoneNumber phoneNumber = new PhoneNumber("010", "400-8080-105");Customer customer = new Customer("C1001", "李項(xiàng)", phoneNumber, address); ???System.out.println("客戶(hù) = " + customer.toString());}
控制臺(tái)輸出:客戶(hù)= Customer[id=C1001, name=李項(xiàng), phoneNumber=PhoneNumber[areaCode=010, number=400-8080-105], address=Address[city=北京, address=大興區(qū)涼水河二街9號(hào)10棟三層, zipcode=100176]]
1.2.1.9 instanceof 判斷Record類(lèi)型
instanceof 能夠與 Java Record一起使用董虱。編譯器知道記錄組件的確切數(shù)量和類(lèi)型。
step1:聲明Person Record,擁有兩個(gè)屬性name和agepublic record Person(String name,Integer age) {}
step2: 在一個(gè)業(yè)務(wù)方法判斷當(dāng)是Record類(lèi)型時(shí)愤诱,繼續(xù)判斷age年齡是否滿(mǎn)足18歲云头。
public class SomeService {public boolean isEligible(Object obj){// 判斷obj為Person 記錄類(lèi)型if( obj instanceof Person(String name, Integer age)){return age >= 18;}return false;}}instanceof 還可以下面的方式if( obj instanceof Person(String name, Integer age) person){return person.age() >= 18;}或者if( obj instanceof Person p){return p.age() >= 18;}public static void main(String[] args) {SomeService service = new SomeService();boolean flag = service.isEligible(new Person("李四", 20)); ?System.out.println("年齡符合嗎?" + flag);}
step3: 測(cè)試代碼
控制臺(tái)輸出:控制臺(tái)輸出flag為true
處理判斷中Record為nullJava Record能夠自動(dòng)處理null淫半。step1:record為nullpublic static void main(String[] args) {SomeService service = new SomeService();boolean eligible = service.isEligible(null);System.out.println("年齡符合嗎溃槐?" + eligible);}控制臺(tái)輸出eligible為false ,Debug調(diào)試代碼科吭,發(fā)現(xiàn)if語(yǔ)句判斷為false昏滴,不執(zhí)行
*總結(jié)*1. abstract類(lèi)java.lang.Record是所有Record的父類(lèi)。2. 有對(duì)于equals()对人,hashCode()谣殊,toString()方法的定義說(shuō)明3. Record類(lèi)能夠?qū)崿F(xiàn) java.io.Serializable序列化或反序列化4. Record支持泛型,例如 record Gif( T t ) { }5. java.lang.Class類(lèi)與Record類(lèi)有關(guān)的兩個(gè)方法:boolean?isRecord()?:?判斷一個(gè)類(lèi)是否是Record類(lèi)型RecordComponent[]?getRecordComponents():Record的數(shù)組牺弄,表示此記錄類(lèi)的所有記錄組件
Customer customer = new Customer(....);RecordComponent[] recordComponents = customer.getClass().getRecordComponents();? ?
for (RecordComponent recordComponent : recordComponents) {System.out.println("recordComponent = " + recordComponent);}boolean record = customer.getClass().isRecord();System.out.println("record = " + record);
1.2.2 Switch
Switch的三個(gè)方面姻几,參考:JEP 361
[if !supportLists]·?[endif]支持箭頭表達(dá)式
[if !supportLists]·?[endif]支持yied返回值
[if !supportLists]·?[endif]支持Java Record
1.2.2.1 箭頭表達(dá)式,新的case標(biāo)簽
Switch新的語(yǔ)法势告,case label -> 表達(dá)式|throw 語(yǔ)句|blockcase label_1, label_2, ..., label_n -> expression;|throw-statement;|block
step1:新的case 標(biāo)簽week:表示周日(1)到周六(7)鲜棠,1和7是休息日,其他是工作日培慌。如果1-7以外為無(wú)需日期
public static void main(String[] args) {int week = 7;String memo = "";switch (week){case 1 -> memo = "星期日豁陆,休息";case 2,3,4,5,6-> memo="工作日";case 7 -> memo="星期六,休息";default -> ?throw new IllegalArgumentException("無(wú)效的日期:");}System.out.println("week = " + memo);}
1.2.2.2 yeild返回值
yeild讓switch作為表達(dá)式吵护,能夠返回值
語(yǔ)法變量= switch(value) { case v1:?yield 結(jié)果值; case v2: yield 結(jié)果值盒音;case v3,v4,v5.. yield 結(jié)果值 }
示例:yield返回值,跳出switch塊public static void main(String[] args) {int week = 2;//yield是switch的返回值馅而, yield跳出當(dāng)前switch塊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);
}
無(wú)需中間變量瓮恭,switch作為表達(dá)式計(jì)算雄坪,可以得到結(jié)果。yield是表達(dá)式的返回值
示例:多表達(dá)式屯蹦,case 與yield 結(jié)合使用
public static void main(String[] args) {int week = 1;//yield是switch的返回值维哈, yield跳出當(dāng)前switch塊String memo ?= switch (week){case 1 ->{System.out.println("week=1的 表達(dá)式部分");yield "星期日,休息";}case 2,3,4,5,6 ->{System.out.println("week=2,3,4,5,6的 表達(dá)式部分");yield "工作日";}case 7 -> {System.out.println("week=7的 表達(dá)式部分");yield "星期六登澜,休息";}default -> {System.out.println("其他語(yǔ)句");yield "無(wú)效日期";}};System.out.println("week = " + memo);}
提示:case 標(biāo)簽->? 與 case 標(biāo)簽:不能混用阔挠。 ? ?一個(gè)switch語(yǔ)句塊中使用一種語(yǔ)法格式。switch作為表達(dá)式脑蠕,賦值給變量购撼,需要yield或者case 標(biāo)簽-> 表達(dá)式跪削。->右側(cè)表達(dá)式為case返回值。
示例:
public static void main(String[] args) {int week = 1;//yield是switch的返回值迂求, yield跳出當(dāng)前switch塊String memo ?= switch (week){case 1 ->{System.out.println("week=1的 表達(dá)式部分");yield "星期日碾盐,休息";}case 2,3,4,5,6 ->{System.out.println("week=2,3,4,5,6的 表達(dá)式部分");yield "工作日";}case 7 -> "星期六,休息";default -> "無(wú)效日期";};System.out.println("week = " + memo);}
1.2.2.3 Java Record
switch表達(dá)式中使用record揩局,結(jié)合 case 標(biāo)簽-> 表達(dá)式毫玖,yield實(shí)現(xiàn)復(fù)雜的計(jì)算step1: 準(zhǔn)備三個(gè)Record
public record Line(int x,int y) {}public record Rectangle(int width,int height) {}public record Shape(int width,int height) {}
step2: switch record
public static void main(String[] args) {Line line = new Line(10,100);Rectangle rectangle = new Rectangle(100,200);Shape shape = new Shape(200,200);Object obj = rectangle;int result = switch (obj){case Line(int x,int y) -> {System.out.println("圖形是線, X:"+x+",Y:"+y);yield x+y;}case Rectangle(int w,int h) -> w * h;case Shape(int w,int h) ->{System.out.println("這是圖形谐腰,要計(jì)算周長(zhǎng)");yield 2* (w + h);}default -> throw new IllegalStateException("無(wú)效的對(duì)象:" + obj);};System.out.println("result = " + result);}
case Line , Rectangle孕豹,Shape 在代碼塊執(zhí)行多條語(yǔ)句涩盾,或者箭頭->表達(dá)式十气。
1.2.3 Text Block
Text Block處理多行文本十分方便,省時(shí)省力春霍。無(wú)需連接 "+",單引號(hào)砸西,換行符等。Java 15 ,參考JEP 378.
1.2.3.1 認(rèn)識(shí)文本塊
語(yǔ)法:使用三個(gè)雙引號(hào)字符括起來(lái)的字符串."""內(nèi)容"""
例如:String name = """lisi"""; //Error 不能將文本塊放在單行上String name= """lisi20""";? //Error 文本塊的內(nèi)容不能在沒(méi)有中間行結(jié)束符的情況下跟隨三個(gè)開(kāi)頭雙引號(hào)
String myname= """zhangsan20""";?//正確
文本塊定義要求:v文本塊以三個(gè)雙引號(hào)字符開(kāi)始址儒,后跟一個(gè)行結(jié)束符芹枷。v不能將文本塊放在單行上v文本塊的內(nèi)容也不能在沒(méi)有中間行結(jié)束符的情況下跟隨三個(gè)開(kāi)頭雙引號(hào)
三個(gè)雙引號(hào)字符""" 與兩個(gè)雙引號(hào)""的字符串處理是一樣的。與普通字符串一樣使用莲趣。例如equals() , "==" , 連接字符串(”+“)鸳慈, 作為方法的參數(shù)等。
1.2.3.2 文本塊與普通的雙引號(hào)字符串一樣
Text Block使用方式與普通字符串一樣喧伞,==走芋,equals比較,調(diào)用String類(lèi)的方法潘鲫。
step1:字符串比較與方法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""";//字符串方法substringString sub = msg.substring(0, 5);System.out.println("sub = " + sub);}
step2:輸出結(jié)果b1 = trueb2 = truesub = hello
1.2.3.3 空白
[if !supportLists]1.?[endif]JEP 378中包含空格處理的詳細(xì)算法說(shuō)明翁逞。
[if !supportLists]2.?[endif]Text Block中的縮進(jìn)會(huì)自動(dòng)去除,左側(cè)和右側(cè)的溉仑。
[if !supportLists]3.?[endif]要保留左側(cè)的縮進(jìn)挖函,空格。將文本塊的內(nèi)容向左移動(dòng)(tab鍵)
示例:
public void fun2(){//按tab向右移動(dòng)浊竟,保留左側(cè)空格String html= """動(dòng)力節(jié)點(diǎn)怨喘,Java黃埔軍校""";System.out.println( html);}
示例2:indent()方法
public void fun3(){String colors= """redgreenblue""";System.out.println( colors);//indent(int space)包含縮進(jìn),space空格的數(shù)量String indent = colors.indent(5);System.out.println( indent);}
輸出:redgreenblue
red green blue
1.2.3.4 文本塊的方法Text Block的格式方法formatted()
public void fun4(){String info= """Name:%sPhone:%sAge:%d""".formatted("張三","13800000000",20);System.out.println("info = " + info);}
String stripIndent():刪除每行開(kāi)頭和結(jié)尾的空白String translateEscapes() :轉(zhuǎn)義序列轉(zhuǎn)換為字符串字面量1.2.3.5 轉(zhuǎn)義字符新的轉(zhuǎn)義字符"",表示隱士換行符振定,這個(gè)轉(zhuǎn)義字符被Text Block轉(zhuǎn)義為空格哲思。通常用于是拆分非常長(zhǎng)的字符串文本 ,串聯(lián)多個(gè)較小子字符串吩案,包裝為多行生成字符串棚赔。
新的轉(zhuǎn)義字符,組合非常長(zhǎng)的字符串。
示例
public void fun5(){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 = " + str);}
輸出:Spring Boot是一個(gè)快速開(kāi)發(fā)框架 基于Spring框架,創(chuàng)建Spring應(yīng)用 內(nèi)嵌Web服務(wù)器胧后,以jar或war方式運(yùn)行
總結(jié):1.多行字符串芋浮,應(yīng)該使用Text Block2.當(dāng)Text Block可以提高代碼的清晰度時(shí),推薦使用壳快。比如代碼中嵌入SQL語(yǔ)句3.避免不必要的縮進(jìn)纸巷,開(kāi)頭和結(jié)尾部分。4.使用空格或僅使用制表符 文本塊的縮進(jìn)眶痰×鲋迹混合空白將導(dǎo)致不規(guī)則的縮進(jìn)。5.對(duì)于大多數(shù)多行字符串竖伯, 分隔符位于上一行的右端存哲,并將結(jié)束分隔符位于文本塊單獨(dú)行上。例如:String colors= """redgreenblue""";
1.2.4 var
在JDK 10及更高版本中七婴,您可以使用var標(biāo)識(shí)符聲明具有非空初始化式的局部變量祟偷,這可以幫助您編寫(xiě)簡(jiǎn)潔的代碼,消除冗余信息使代碼更具可讀性打厘,謹(jǐn)慎使用.
1.2.4.1 var 聲明局部變量
var特點(diǎn)
[if !supportLists]1.?[endif]var是一個(gè)保留字修肠,不是關(guān)鍵字(可以聲明var為變量名)
[if !supportLists]2.?[endif]方法內(nèi)聲明的局部變量,必須有初值
[if !supportLists]3.?[endif]每次聲明一個(gè)變量户盯,不可復(fù)合聲明多個(gè)變量嵌施。var s1="Hello", age=20;?//Error
[if !supportLists]4.?[endif]var動(dòng)態(tài)類(lèi)型是編譯器根據(jù)變量所賦的值來(lái)推斷類(lèi)型
[if !supportLists]5.?[endif]var代替顯示類(lèi)型,代碼簡(jiǎn)潔先舷,減少不必要的排版艰管,混亂。
var優(yōu)缺點(diǎn)
[if !supportLists]·?[endif]代碼簡(jiǎn)潔和整齊蒋川。
[if !supportLists]·?[endif]降低了程序的可讀性(無(wú)強(qiáng)類(lèi)型聲明)
示例:
//通常try (Stream result = dbconn.executeQuery(query)) {//...//推薦try (var customers = dbconn.executeQuery(query)) {//...}比較Stream result 與 ?var customers
1.2.4.2 使用時(shí)候使用var
[if !supportLists]·?[endif]簡(jiǎn)單的臨時(shí)變量
[if !supportLists]·?[endif]復(fù)雜牲芋,多步驟邏輯,嵌套的表達(dá)式等捺球,簡(jiǎn)短的變量有助理解代碼
[if !supportLists]·?[endif]能夠確定變量初始值
[if !supportLists]·?[endif]變量類(lèi)型比較長(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 strings = Arrays.asList("a", "b", "c");for (var str: strings){System.out.println("str = " + str);}}
1.2.5 sealed
sealed 翻譯為密封缸浦,密封類(lèi)(Sealed Classes)的首次提出是在 Java15 的 JEP 360 中,并在 Java 16 的 JEP 397 再次預(yù)覽氮兵,而在 Java 17 的 JEP 409 成為正式的功能裂逐。
Sealed Classes主要特點(diǎn)是限制繼承
Sealed Classes主要特點(diǎn)是限制繼承,Java中通過(guò)繼承增強(qiáng)泣栈,擴(kuò)展了類(lèi)的能力卜高,復(fù)用某些功能弥姻。當(dāng)這種能力不受控。與原有類(lèi)的設(shè)計(jì)相違背掺涛,導(dǎo)致不預(yù)見(jiàn)的異常邏輯庭敦。
Sealed Classes限制無(wú)限的擴(kuò)張。
Java中已有sealed 的設(shè)計(jì)
[if !supportLists]·?[endif]final關(guān)鍵字薪缆,修飾類(lèi)不能被繼承
[if !supportLists]·?[endif]private限制私有類(lèi)
sealed 作為關(guān)鍵字可在class和interface上使用秧廉,結(jié)合permits 關(guān)鍵字。定義限制繼承的密封類(lèi)
1.2.5.1 Sealed Classes
sealed class 類(lèi)名 permits 子類(lèi)1,子類(lèi)N列表 {}
step1::聲明sealed Class
public sealed class Shape permits Circle, Square, Rectangle {private Integer width;private Integer height;public void draw(){System.out.println("=Shape圖形");}}
permits表示允許的子類(lèi)拣帽,一個(gè)或多個(gè)
step2::聲明子類(lèi)
子類(lèi)聲明有三種
[if !supportLists]1.?[endif]final?終結(jié)疼电,依然是密封的
[if !supportLists]2.?[endif]sealed?子類(lèi)是密封類(lèi),需要子類(lèi)實(shí)現(xiàn)
[if !supportLists]3.?[endif]non-sealed?非密封類(lèi)减拭,擴(kuò)展使用蔽豺,不受限
示例:
//第一種 finalpublic final class Circle extends Shape {}//第二種 sealed classpublic sealed class Square extends Shape permits RoundSquare {@Override ?public void draw() {System.out.println("=Square圖形");}}//密封類(lèi)的子類(lèi)的子類(lèi)public final class RoundSquare extends Square{}//非密封類(lèi) , 可以被擴(kuò)展峡谊。放棄密封public non-sealed class Rectangle extends Shape {}//繼承非密封類(lèi)public class Line extends ?Rectangle{}
密封類(lèi)不支持匿名類(lèi)與函數(shù)式接口
1.2.5.2 Sealed Interface
密封接口同密封類(lèi)
step1:聲明密封接口
public sealed interface SomeService permits SomeServiceImpl {void doThing();}
step2:實(shí)現(xiàn)接口
public final class SomeServiceImpl implements SomeService {@Override ?public void doThing() {}}
以上類(lèi)和接口要在同一包可訪問(wèn)范圍內(nèi)茫虽。