Java程序員必備基礎(chǔ):JDK 5-15都有哪些經(jīng)典新特性
前言
JDK 15發(fā)布啦~ 我們一起回顧JDK 5-15 的新特性吧,大家一起學(xué)習(xí)哈~
本文已經(jīng)收錄到github
?https://github.com/whx123/JavaHome
?
「公眾號(hào):撿田螺的小男孩」
Java 5 新特性

1. 泛型
泛型本質(zhì)是參數(shù)化類(lèi)型,解決不確定具體對(duì)象類(lèi)型的問(wèn)題。
?List?strList=new?ArrayList();
2. 增強(qiáng)循環(huán)(for-each)
for-each循環(huán)簡(jiǎn)化了集合的遍歷。
String?[]?str?=?{"關(guān)注","公眾號(hào)","撿田螺的小男孩"};
for?(String?temp:str)?{
?????System.out.println(temp);
}
3. 自動(dòng)封箱拆箱
自動(dòng)裝箱: 就是將基本數(shù)據(jù)類(lèi)型自動(dòng)轉(zhuǎn)換成對(duì)應(yīng)的包裝類(lèi)。 自動(dòng)拆箱:就是將包裝類(lèi)自動(dòng)轉(zhuǎn)換成對(duì)應(yīng)的基本數(shù)據(jù)類(lèi)型。
包裝類(lèi)型有:Integer,Double,Float,Long,Short,Character和Boolean
Integer?i?=666;??//自動(dòng)裝箱
int?a=?i;?????//自動(dòng)拆箱
4. 枚舉
關(guān)鍵字enum可以將一組具名的值的有限集合創(chuàng)建為一種新的類(lèi)型,而這些具名的值可以作為常規(guī)的程序組件使用,這就是枚舉類(lèi)型。
enum?SeasonEnum?{
????SPRING,SUMMER,FALL,WINTER;
}
5. 可變參數(shù)
我們?cè)诙x方法參數(shù)的時(shí)候不確定定義多少個(gè),就可以定義為「可變參數(shù)」,它本質(zhì)上是一個(gè)「數(shù)組」。
public?static?void?main(String[]?args)?throws?Exception?{
????String?[]?str?=?{"關(guān)注","公眾號(hào)","撿田螺的小男孩"};
????testVarargs(str);
????String?str1?=?"關(guān)注公眾號(hào),撿田螺的小男孩";
????testVarargs(str1);
}
//可變參數(shù)String...?args
private?static?void?testVarargs(String...?args)?{
????for?(String?arg?:?args)?{
????????System.out.println(arg);
????}
}
6. 注解
可以把注解理解為代碼里的特殊標(biāo)記,這些標(biāo)記可以在編譯,類(lèi)加載,運(yùn)行時(shí)被讀取,并執(zhí)行相應(yīng)的處理。
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public?@interface?Override?{
}
7.靜態(tài)導(dǎo)入
通過(guò)import static類(lèi),就可以使用類(lèi)里的靜態(tài)變量或方法。看一下例子哈~
import?static?java.lang.System.out;?//靜態(tài)導(dǎo)入System類(lèi)的靜態(tài)變量out
public?class?Test?{
????public?static?void?main(String[]?args)?throws?Exception?{
????????String?str1?=?"關(guān)注公眾號(hào),撿田螺的小男孩";
????????System.out.println(str1);?//常規(guī)寫(xiě)法
????????out.println(str1);??//靜態(tài)導(dǎo)入,可以直接使用out輸出
????}
}
8. 線程并發(fā)庫(kù)(JUC)
JDK5 豐富了線程處理功能,java.util.concurrent包提供了以下的類(lèi)、接口:
??
線程池:ExecutorService接口 線程護(hù)斥:Lock 類(lèi) 線程通信:Condition接口 同步隊(duì)列:ArrayBlockingQueue類(lèi) 同步集合:ConcurrentHashMap類(lèi)
Java 6 新特性

1.Desktop類(lèi)和SystemTray類(lèi)
JDK 6在java.awt包下,新增了兩個(gè)類(lèi):Desktop類(lèi)和SystemTray類(lèi)
??
「Desktop類(lèi)」: 用來(lái)打開(kāi)系統(tǒng)默認(rèn)瀏覽器瀏覽指定的URL,打開(kāi)系統(tǒng)默認(rèn)郵件客戶端發(fā)郵件等 「SystemTray類(lèi)」:用來(lái)在系統(tǒng)托盤(pán)區(qū)創(chuàng)建一個(gè)托盤(pán)程序,如果在微軟的Windows上,它被稱為“任務(wù)欄”狀態(tài)區(qū)域。
//獲取Desktop實(shí)例
Desktop?desktop?=?Desktop.getDesktop();
desktop.browse(URI.create("https://www.baidu.com"));
2. 使用JAXB2來(lái)實(shí)現(xiàn)對(duì)象與XML之間的映射
JAXB,即Java Architecture for XML Binding,可以實(shí)現(xiàn)對(duì)象與XML之間的映射,常用注解如下:
??
@XmlRootElement:注解在類(lèi)上面,對(duì)應(yīng)xml的跟元素,使用name屬性定義根節(jié)點(diǎn)的名稱。 @XmlElement:指定一個(gè)字段或get/set方法映射到xml的節(jié)點(diǎn),使用name屬性定義這個(gè)根節(jié)點(diǎn)的名稱。 @XmlAttribute:將JavaBean對(duì)象的屬性映射為xml的屬性,使用name屬性為生成的xml屬性指定別名。 @XmlAccessorType:定義映射這個(gè)類(lèi)中的何種類(lèi)型都需要映射到xml。 @XmlSchema: 將包映射到XML名稱空間
「看個(gè)例子吧~」
public?class?JAXB2XmlTest?{
????public?static?void?main(String[]?args)?throws?JAXBException,?IOException?{
????????
????????List?list?=?new?ArrayList<>();
????????list.add(new?Singer("jay",?8));
????????list.add(new?Singer("eason",?10));
????????SingerList?singerList?=?new?SingerList();
????????singerList.setSingers(list);
????????String?str?=?JAXB2XmlTest.beanToXml(singerList,?SingerList.class);
????????String?path?=?"C:\\jay.txt";
????????BufferedWriter?bfw?=?new?BufferedWriter(new?FileWriter(new?File(path)));
????????bfw.write(str);
????????bfw.close();
????}
????private?static?String?beanToXml(Object?obj,?Class>?load)?throws?JAXBException?{
????????JAXBContext?context?=?JAXBContext.newInstance(load);
????????Marshaller?marshaller?=?context.createMarshaller();
????????marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT,?true);
????????marshaller.setProperty(Marshaller.JAXB_ENCODING,?"GBK");
????????StringWriter?writer?=?new?StringWriter();
????????marshaller.marshal(obj,writer);
????????return?writer.toString();
????}
}
public?class?Singer?{
????private?String?name;
????private?int?age;
????public?Singer(String?name,?int?age)?{
????????this.name?=?name;
????????this.age?=?age;
????}
????@XmlAttribute(name="name")
????public?String?getName()?{
????????return?name;
????}
????public?void?setName(String?name)?{
????????this.name?=?name;
????}
????@XmlAttribute(name="age")
????public?int?getAge()?{
????????return?age;
????}
????public?void?setAge(int?age)?{
????????this.age?=?age;
????}
}
@XmlRootElement(name="list")
public?class?SingerList?{
????private?List?singers;
????
????@XmlElement(name="singer")
????public?List?getSingers()?{
????????return?singers;
????}
????public?void?setSingers(List?singers)?{
????????this.singers?=?singers;
????}
}
「運(yùn)行效果:」
"1.0"?encoding="GBK"?standalone="yes"?>
????"8"?name="jay"/>
????"10"?name="eason"/>
3.輕量級(jí) Http Server API
JDK 6中提供了簡(jiǎn)單的Http Server API,可以構(gòu)建嵌入式Http服務(wù)器,同時(shí)支持Http和Https協(xié)議。HttpServer會(huì)調(diào)用HttpHandler實(shí)現(xiàn)類(lèi)的回調(diào)方法來(lái)處理客戶端請(qǐng)求,這里用戶只需實(shí)現(xiàn)HttpHandler接口就可以了。
/**
?*?根據(jù)Java提供的API實(shí)現(xiàn)Http服務(wù)器
?*/
public?class?MyHttpServer?{
????/**
?????*?@param?args
?????*?@throws?IOException
?????*/
????public?static?void?main(String[]?args)?throws?IOException?{
????????//創(chuàng)建HttpServer服務(wù)器
????????HttpServer?httpServer?=?HttpServer.create(new?InetSocketAddress(8080),?10);
????????//將?/jay請(qǐng)求交給MyHandler處理器處理
????????httpServer.createContext("/",?new?MyHandler());
????????httpServer.start();
????}
}
public?class?MyHandler?implements?HttpHandler?{
????public?void?handle(HttpExchange?httpExchange)?throws?IOException?{
????????//請(qǐng)求頭
????????Headers?headers?=?httpExchange.getRequestHeaders();
????????Set>>?entries?=?headers.entrySet();
????????StringBuffer?response?=?new?StringBuffer();
????????for?(Map.Entry>?entry?:?entries){
????????????response.append(entry.toString()?+?"\n");
????????}
????????//設(shè)置響應(yīng)頭屬性及響應(yīng)信息的長(zhǎng)度
????????httpExchange.sendResponseHeaders(200,?response.length());
????????//獲得輸出流
????????OutputStream?os?=?httpExchange.getResponseBody();
????????os.write(response.toString().getBytes());
????????os.close();
????}
}
4. 插入式注解處理API
?JDK 6提供了插入式注解處理API,可以讓我們定義的注解在編譯期而不是運(yùn)行期生效,從而可以在編譯期修改字節(jié)碼。lombok框架就是使用該特性來(lái)實(shí)現(xiàn)的,Lombok通過(guò)注解的方式,在編譯時(shí)自動(dòng)為屬性生成構(gòu)造器、getter/setter、equals、hashcode、toString等方法,大大簡(jiǎn)化了代碼的開(kāi)發(fā)。
?
5. STAX
STAX,是JDK6中一種處理XML文檔的API。
public?class?STAXTest?{
????public?static?void?main(String[]?args)?throws?Exception?{
????????XMLInputFactory?xmlInputFactory?=?XMLInputFactory.newInstance();
????????XMLEventReader?xmlEventReader?=?xmlInputFactory.createXMLEventReader(new?FileInputStream("C:\\jay.xml"));
????????XMLEvent?event?=?null;
????????StringBuffer?stringBuffer?=?new?StringBuffer();
????????while?(xmlEventReader.hasNext())?{
????????????event?=?xmlEventReader.nextEvent();
????????????stringBuffer.append(event.toString());
????????}
????????System.out.println("xml文檔解析結(jié)果:");
????????System.out.println(stringBuffer);
????}
}
「運(yùn)行結(jié)果:」
xml文檔解析結(jié)果:
"1.0"?encoding='GBK'?standalone='yes'?>
????'jay'?age='8'>
????'eason'?age='10'>
ENDDOCUMENT
6. Common Annotations
?Common annotations原本是Java EE 5.0(JSR 244)規(guī)范的一部分,現(xiàn)在SUN把它的一部分放到了Java SE 6.0中。隨著Annotation元數(shù)據(jù)功能加入到Java SE 5.0里面,很多Java 技術(shù)都會(huì)用Annotation部分代替XML文件來(lái)配置運(yùn)行參數(shù)。
?
以下列舉Common Annotations 1.0里面的幾個(gè)Annotations:
@Generated:用于標(biāo)注生成的源代碼 @Resource: 用于標(biāo)注所依賴的資源,容器據(jù)此注入外部資源依賴,有基于字段的注入和基于setter方法的注入兩種方式 。 @Resources:同時(shí)標(biāo)注多個(gè)外部依賴,容器會(huì)把所有這些外部依賴注入 @PostConstruct:標(biāo)注當(dāng)容器注入所有依賴之后運(yùn)行的方法,用來(lái)進(jìn)行依賴注入后的初始化工作,只有一個(gè)方法可以標(biāo)注為PostConstruct 。 @PreDestroy:當(dāng)對(duì)象實(shí)例將要被從容器當(dāng)中刪掉之前,要執(zhí)行的回調(diào)方法要標(biāo)注為PreDestroy
7. Compiler API
javac編譯器可以把.java的源文件編譯為.class文件,JDK 6的新特性Compiler API(JSR 199)也可以動(dòng)態(tài)編譯Java源文件。
public?class?CompilerApiTest?{
????public?static?void?main(String[]?args)?throws?Exception?{
????????JavaCompiler?javaCompiler?=?ToolProvider.getSystemJavaCompiler();
????????StandardJavaFileManager?standardJavaFileManager?=?javaCompiler.getStandardFileManager(null,null,null);
????????Iterable?extends?JavaFileObject>?javaFileObjects?=?standardJavaFileManager.getJavaFileObjects("C:\\Singer.java");
????????javaCompiler.getTask(null,?standardJavaFileManager,?null,?null,?null,?javaFileObjects).call();
????????standardJavaFileManager.close();
????}
}
運(yùn)行結(jié)果:會(huì)在C目錄生成Singer.class文件
8. 對(duì)腳本語(yǔ)言的支持(如: ruby, groovy, javascript)
JDK6增加了對(duì)腳本語(yǔ)言的支持(JSR 223),原理是將腳本語(yǔ)言編譯成字節(jié)碼,這樣腳本語(yǔ)言也能享用Java平臺(tái)的諸多優(yōu)勢(shì),包括可移植性,安全等。JDK6實(shí)現(xiàn)包含了一個(gè)基于Mozilla Rhino的 腳本語(yǔ)言引擎,因此可以支持javascript,當(dāng)然JDK也支持ruby等其他語(yǔ)言
public?class?JavaScriptTest?{
????public?static?void?main(String[]?args)?throws?Exception?{
????????ScriptEngineManager?factory?=?new?ScriptEngineManager();
????????ScriptEngine?engine?=?factory.getEngineByName("JavaScript");
????????String?script;
????????try?{
????????????script?=?"print('Hello')";
????????????engine.eval(script);//?執(zhí)行腳本
????????}catch?(Exception?e)?{
????????????e.printStackTrace();
????????}
????}
}
//output
Hello
Java 7 新特性

1.switch 支持String字符串類(lèi)型。
String?singer?=?"jay";
switch?(singer)?{
???????case?"jay"?:
????????????System.out.println("周杰倫");
?????????????break;
???????case?"eason"?:
????????????System.out.println("陳奕迅");
????????????break?;
???????default?:
????????????System.out.println("其他");
????????????break?;
???}
2.try-with-resources,資源自動(dòng)關(guān)閉
JDK 7 之前:
BufferedReader?br?=?new?BufferedReader(new?FileReader("d:七里香.txt"));
try?{
???return?br.readLine();
}?finally?{
???br.close();
}
JDK 7 之后:
/*
?*?聲明在try括號(hào)中的對(duì)象稱為資源,在方法執(zhí)行完畢后會(huì)被自動(dòng)關(guān)閉
?*/
try?(BufferedReader?br?=?new?BufferedReader(new?FileReader("d:七里香.txt"))?{
???return?br.readLine();
}
3. 整數(shù)類(lèi)型如(byte,short,int,long)能夠用二進(jìn)制來(lái)表示
//0b或者0B表示二進(jìn)制
int?a?=?0b010;
int?b?=?0B010;
4. 數(shù)字常量支持下劃線
int?a?=?11_11;//a的值為1111,下劃線不影響實(shí)際值,提升可讀性
5. 泛型實(shí)例化類(lèi)型自動(dòng)推斷,即”<>”
JDK 7 之前:
Map>?map?=?new?HashMap>();
JDK 7之后:
//不須聲明類(lèi)型,自動(dòng)根據(jù)前面<>推斷其類(lèi)型
Map>?map?=?new?HashMap<>();
6.一個(gè)catch中捕獲多個(gè)異常類(lèi)型,用(|)分隔開(kāi)
JDK 7之前
try{
???//do?something
}?catch?(FirstException?e)?{
?????logger.error(e);
}?catch?(SecondException?e)?{
?????logger.error(ex);
}
JDk 7之后
try{
???//do?something
}?catch?(FirstException?|?SecondException?e)?{
?????logger.error(e);
}
7. 增強(qiáng)的文件系統(tǒng)
Java7 提供了全新的NIO2.0 API,方便文件管理的編碼。如,可以在java.nio.file包下使用Path、Paths、Files、WatchService等常用類(lèi)型。
Path?path?=?Paths.get("C:\\jay\\七里香.txt");?//創(chuàng)建Path對(duì)象
byte[]?bytes=?Files.readAllBytes(path);??//讀取文件
System.out.println(path.getFileName());?//獲取當(dāng)前文件名稱
System.out.println(path.toAbsolutePath());?//?獲取文件絕對(duì)路徑
System.out.println(new?String(bytes,?"utf-8"));
8. Fork/join 框架
Java7提供的一個(gè)用于并行執(zhí)行任務(wù)的框架,是一個(gè)把大任務(wù)分割成若干個(gè)小任務(wù),最終匯總每個(gè)小任務(wù)結(jié)果后得到大任務(wù)結(jié)果的框架。
Fork/join計(jì)算1-1000累加值:
public?class?ForkJoinPoolTest?{
????private?static?final?Integer?DURATION_VALUE?=?100;
????static?class?ForkJoinSubTask?extends?RecursiveTask{
????????//?子任務(wù)開(kāi)始計(jì)算的值
????????private?Integer?startValue;
????????//?子任務(wù)結(jié)束計(jì)算的值
????????private?Integer?endValue;
????????private?ForkJoinSubTask(Integer?startValue?,?Integer?endValue)?{
????????????this.startValue?=?startValue;
????????????this.endValue?=?endValue;
????????}
????????@Override
????????protected?Integer?compute()?{
????????????//小于一定值DURATION,才開(kāi)始計(jì)算
????????????if(endValue?-?startValue?????????????????System.out.println("執(zhí)行子任務(wù)計(jì)算:開(kāi)始值?=?"?+?startValue?+?";結(jié)束值?=?"?+?endValue);
????????????????Integer?totalValue?=?0;
????????????????for?(int?index?=?this.startValue;?index?<=?this.endValue;?index++)?{
????????????????????totalValue?+=?index;
????????????????}
????????????????return?totalValue;
????????????}?else?{
????????????????//?將任務(wù)拆分,拆分成兩個(gè)任務(wù)
????????????????ForkJoinSubTask?subTask1?=?new?ForkJoinSubTask(startValue,?(startValue?+?endValue)?/?2);
????????????????subTask1.fork();
????????????????ForkJoinSubTask?subTask2?=?new?ForkJoinSubTask((startValue?+?endValue)?/?2?+?1?,?endValue);
????????????????subTask2.fork();
????????????????return?subTask1.join()?+?subTask2.join();
????????????}
????????}
????}
????public?static?void?main(String[]?args)?throws?ExecutionException,?InterruptedException?{
????????//?Fork/Join框架的線程池
????????ForkJoinPool?pool?=?new?ForkJoinPool();
????????ForkJoinTask?taskFuture?=??pool.submit(new?ForkJoinSubTask(1,1000));
????????Integer?result?=?taskFuture.get();
????????System.out.println("累加結(jié)果是:"?+?result);
????}
}
運(yùn)行結(jié)果:
...
執(zhí)行子任務(wù)計(jì)算:開(kāi)始值?=?189;結(jié)束值?=?250
執(zhí)行子任務(wù)計(jì)算:開(kāi)始值?=?251;結(jié)束值?=?313
執(zhí)行子任務(wù)計(jì)算:開(kāi)始值?=?314;結(jié)束值?=?375
執(zhí)行子任務(wù)計(jì)算:開(kāi)始值?=?376;結(jié)束值?=?438
執(zhí)行子任務(wù)計(jì)算:開(kāi)始值?=?439;結(jié)束值?=?500
執(zhí)行子任務(wù)計(jì)算:開(kāi)始值?=?501;結(jié)束值?=?563
執(zhí)行子任務(wù)計(jì)算:開(kāi)始值?=?564;結(jié)束值?=?625
執(zhí)行子任務(wù)計(jì)算:開(kāi)始值?=?626;結(jié)束值?=?688
執(zhí)行子任務(wù)計(jì)算:開(kāi)始值?=?689;結(jié)束值?=?750
執(zhí)行子任務(wù)計(jì)算:開(kāi)始值?=?751;結(jié)束值?=?813
執(zhí)行子任務(wù)計(jì)算:開(kāi)始值?=?814;結(jié)束值?=?875
執(zhí)行子任務(wù)計(jì)算:開(kāi)始值?=?876;結(jié)束值?=?938
執(zhí)行子任務(wù)計(jì)算:開(kāi)始值?=?939;結(jié)束值?=?1000
累加結(jié)果是:500500
Java 8 新特性

1.lambada表達(dá)式
Lambda 允許把函數(shù)作為一個(gè)方法的參數(shù),傳遞到方法中
語(yǔ)法格式:
(parameters)?->?expression?或?(parameters)?->{?statements;?}
代碼示例:
Arrays.asList("jay",?"Eason",?"SHE").forEach(
???????(?String?singer?)?->?System.out.print(?singer?+?",")?);
2. 函數(shù)式接口
Lambda的設(shè)計(jì)者為了讓現(xiàn)有的功能與Lambda表達(dá)式很好兼容,設(shè)計(jì)出函數(shù)式接口。
函數(shù)式接口是指只有一個(gè)函數(shù)的接口,可以隱式轉(zhuǎn)換為lambada表達(dá)式。 Java 8 提供了注解@FunctionalInterface,顯示聲明一個(gè)函數(shù)式接口。 java.lang.Runnable和java.util.concurrent.Callable是函數(shù)式接口的例子~
@FunctionalInterface
public?interface?Runnable?{
????public?abstract?void?run();
}
3. 方法引用
方法引用提供了非常有用的語(yǔ)法,可以直接引用已有Java類(lèi)或?qū)ο螅▽?shí)例)的方法或構(gòu)造器。它與Lambda表達(dá)式配合使用,可以減少冗余代碼,使代碼更加簡(jiǎn)潔。
//利用函數(shù)式接口Consumer的accept方法實(shí)現(xiàn)打印,Lambda表達(dá)式如下
Consumer?consumer?=?x?->?System.out.println(x);
consumer.accept("jay");
//引用PrintStream類(lèi)(也就是System.out的類(lèi)型)的println方法,這就是方法引用
consumer?=?System.out::println;
consumer.accept("關(guān)注公眾號(hào)撿田螺的小男孩");
4. 默認(rèn)方法
默認(rèn)方法就是一個(gè)在接口里面有了一個(gè)實(shí)現(xiàn)的方法。它允許將新方法添加到接口,但不強(qiáng)制實(shí)現(xiàn)了該接口的類(lèi)必須實(shí)現(xiàn)新的方法。
public?interface?ISingerService?{
????//?默認(rèn)方法
????default?void?sing(){
????????System.out.println("唱歌");
????}
????void?writeSong();
}
//JaySingerServiceImpl?不用強(qiáng)制實(shí)現(xiàn)ISingerService的默認(rèn)sing()方法
public?class?JaySingerServiceImpl?implements?ISingerService?{
????@Override
????public?void?writeSong()?{
????????System.out.println("寫(xiě)了一首七里香");
????}
}
5.Stream API
Stream API,支持對(duì)元素流進(jìn)行函數(shù)式操作,它集成在Collections API 中,可以對(duì)集合進(jìn)行批量操作。常用API:
filter 篩選 map流映射 reduce 將流中的元素組合起來(lái) collect 返回集合 sorted 排序 flatMap 流轉(zhuǎn)換 limit返回指定流個(gè)數(shù) distinct去除重復(fù)元素
public?class?Singer?{
????private?String?name;
????private?Integer?songNum;
????private?Integer?age;
????...
}
List?singerList?=?new?ArrayList();
singerList.add(new?Singer("jay",?11,?36));
singerList.add(new?Singer("eason",?8,?31));
singerList.add(new?Singer("JJ",?6,?29));
List?singerNameList?=?singerList.stream()
????????????????.filter(singer?->?singer.getAge()?>?30)??//篩選年齡大于30
????????????????.sorted(Comparator.comparing(Singer::getSongNum))??//根據(jù)歌曲數(shù)量排序
????????????????.map(Singer::getName)??//提取歌手名字
????????????????.collect(Collectors.toList());?//轉(zhuǎn)換為L(zhǎng)ist
6. Optional
Java 8引入Optional類(lèi),用來(lái)解決NullPointerException。Optional代替if...else解決空指針問(wèn)題,使代碼更加簡(jiǎn)潔。
if...else 判空
Singer?singer?=?getSingerById("666");
if?(singer?!=?null)?{
????String?name??=?singer.getName();
????System.out.println(name);
}
Optional的判空
Optional?singer?=?Optional.ofNullable(getSingerById("666"));
singer.ifPresent(s?->?System.out.println(s.getName()));
7. Date Time API
JDK 8之前的日期API處理存在非線程安全、時(shí)區(qū)處理麻煩等問(wèn)題。Java 8 在 java.time包下提供了新的日期API,簡(jiǎn)化了日期的處理~
LocalDate?today?=?LocalDate.now();
int?year?=?today.getYear();
System.out.println("今年是"?+?year);
//是否閏年
System.out.println("今年是不是閏年:"?+?today.isLeapYear());
LocalDateTime?todayTime?=?LocalDateTime.now();
System.out.println("當(dāng)前時(shí)間"?+?todayTime);
//時(shí)區(qū)指定
System.out.println("美國(guó)時(shí)間:"?+?ZonedDateTime.of(todayTime,ZoneId.of("America/Los_Angeles")));
????????
LocalDate?specailDate?=?LocalDate.of(2020,?6,?20);
LocalDate?expectDate?=?specailDate.plus(100,?ChronoUnit.DAYS);
System.out.println("比較特別的一天"?+?specailDate);
System.out.println("特殊日期的100天"?+?expectDate);
8. 重復(fù)注解
重復(fù)注解,即一個(gè)注解可以在一個(gè)類(lèi)、屬性或者方法上同時(shí)使用多次;用@Repeatable定義重復(fù)注解
@Repeatable(ScheduleTimes.class)
public?@interface?ScheduleTime?{
????String?value();
}
public?@interface?ScheduleTimes?{
????ScheduleTime[]?value();
}
public?class?ScheduleTimeTask?{
????@ScheduleTime("10")
????@ScheduleTime("12")
????public?void?doSomething()?{?}
}
9. Base64
Java 8把Base64編碼的支持加入到官方庫(kù)中~
String?str?=?"公眾號(hào):撿田螺的小男孩";
String?encoded?=?Base64.getEncoder().encodeToString(str.getBytes(?StandardCharsets.UTF_8));
String?decoded?=?new?String(Base64.getDecoder().decode(encoded),?StandardCharsets.UTF_8);
10. JVM的新特性
使用元空間Metaspace代替持久代(PermGen space),JVM參數(shù)使用-XX:MetaSpaceSize和-XX:MaxMetaspaceSize設(shè)置大小。
Java 9 新特性

1. java模塊系統(tǒng)
什么是模塊化?
?一個(gè)大型系統(tǒng),比如一個(gè)商城網(wǎng)站,它會(huì)包含很多模塊的,如:訂單模塊,用戶信息模塊,商品信息模塊,廣告位模塊等等。各個(gè)模塊之間會(huì)相互調(diào)用。如果每個(gè)模塊單獨(dú)運(yùn)行都會(huì)帶動(dòng)其他所有模塊,性能非常低效。但是,如果某一模塊運(yùn)行時(shí),只會(huì)啟動(dòng)它所依賴的模塊,性能大大提升。這就是JDK 9模塊化的思想。
?
什么是JDK 9模塊化?
?Java 平臺(tái)模塊系統(tǒng),即Project Jigsaw,把模塊化開(kāi)發(fā)實(shí)踐引入到了Java平臺(tái)中。在引入了模塊系統(tǒng)之后,JDK 被重新組織成94個(gè)模塊。Java 應(yīng)用可以通過(guò)新增的jlink 工具,創(chuàng)建出只包含所依賴的JDK模塊的自定義運(yùn)行時(shí)鏡像。這樣可以極大的減少Java運(yùn)行時(shí)環(huán)境的大小。
?
Java 9 模塊的重要特征:
??
在其工件(artifact)的根目錄中包含了一個(gè)描述模塊的 module-info.class 文 件。 工件的格式可以是傳統(tǒng)的 JAR 文件或是 Java 9 新增的 JMOD 文件。 這個(gè)文件由根目錄中的源代碼文件 module-info.java 編譯而來(lái)。 該模塊聲明文件可以描述模塊的不同特征。
在 module-info.java 文件中,我們可以用新的關(guān)鍵詞module來(lái)聲明一個(gè)模塊,如下所示。下面給出了一個(gè)模塊com.mycompany.mymodule的最基本的模塊聲明
module?com.jay.sample?{???//關(guān)鍵詞module來(lái)聲明一個(gè)模塊
????exports?com.jay.sample;?//使用?exports可以聲明模塊對(duì)其他模塊所導(dǎo)出的包。
????requires?com.jay.common;?//使用requires可以聲明模塊對(duì)其他模塊的依賴關(guān)系。
}
2. 不可變集合工廠方法
為了創(chuàng)建不可變集合,JDK9之前醬紫的:
List?stringList?=?new?ArrayList<>();
stringList.add("關(guān)注公眾號(hào):");
stringList.add("撿田螺的小男孩");
List?unmodifiableList?=?Collections.unmodifiableList(stringList);
JDK 9 提供了List.of()、Set.of()、Map.of()和Map.ofEntries()等工廠方法來(lái)創(chuàng)建不可變集合:
List?unmodifiableList?=?List.of("關(guān)注公眾號(hào):","撿田螺的小男孩");
3. 接口支持私有方法
JDK 8支持在接口實(shí)現(xiàn)默認(rèn)方法和靜態(tài)方法,但是不能在接口中創(chuàng)建私有方法,為了避免了代碼冗余和提高閱讀性,JDK 9在接口中支持私有方法。
public?interface?IPrivateInterfaceTest?{
????//JDK?7?之前
????String?a?=?"jay";
????void?method7();
????//JDK?8
????default?void?methodDefault8(){
????????System.out.println("JDK?8新特性默認(rèn)方法");
????}
????static?void?methodStatic8()?{
????????System.out.println("JDk?8新特性靜態(tài)方法");
????}
????
????//Java?9?接口支持私有方法
????private?void?method9(){}
}
4. ?鉆石操作符升級(jí)
鉆石操作符是在 java 7 中引入的,可以讓代碼更易讀,但它不能用于匿名的內(nèi)部類(lèi)。 在 java 9 中, 它可以與匿名的內(nèi)部類(lèi)一起使用,從而提高代碼的可讀性。
//JDK?5,6
Map?map56?=?new?HashMap();
//JDk?7,8
Map?map78?=?new?HashMap<>();
//JDK?9?結(jié)合匿名內(nèi)部類(lèi)的實(shí)現(xiàn)
Map?map9?=?new?HashMap<>(){};
5. Optional 類(lèi)改進(jìn)
java 9 中,java.util.Optional 添加了很多新的有用方法,如:
stream() ifPresentOrElse() or()
ifPresentOrElse 方法的改進(jìn)就是有了 else,接受兩個(gè)參數(shù) Consumer 和 Runnable。
import?java.util.Optional;
?
public?class?OptionalTest?{
???public?static?void?main(String[]?args)?{
??????Optional?optional?=?Optional.of(1);
?
??????optional.ifPresentOrElse(?x?->?System.out.println("Value:?"?+?x),()?->?
?????????System.out.println("Not?Present."));
?
??????optional?=?Optional.empty();
?
??????optional.ifPresentOrElse(?x?->?System.out.println("Value:?"?+?x),()?->?
?????????System.out.println("Not?Present."));
???}??
}
6. 多版本兼容Jar包
?很多公司使用的JDK都是老版本的,JDK6、JDk5 ,甚至JDk4的,不是他們不想升級(jí)JDk版本,而是擔(dān)心兼容性問(wèn)題。JDK 9的一個(gè)新特性,多版本兼容Jar包解決了這個(gè)問(wèn)題。舉個(gè)例子:假設(shè)你一直用的是小米8,已經(jīng)非常習(xí)慣它的運(yùn)行流程了,突然出來(lái)小米9,即使小米9很多新功能引人入勝,但是有些人不會(huì)輕易買(mǎi)小米9,因?yàn)橐呀?jīng)已經(jīng)習(xí)慣小米8的流程。同理,為什么很多公司不升級(jí)JDK,就是在此。但是呢,JDK 9的這個(gè)功能很強(qiáng)大,它可以讓你的版本升級(jí)到JDK 9,但是還是老版本的運(yùn)行流程,即在老的運(yùn)行流程繼承新的功能~
?
7. JShell工具
jShell工具相當(dāng)于cmd工具,然后呢,你可以像在cmd工具操作一樣,直接在上面運(yùn)行Java方法,Java語(yǔ)句等~
jshell>?System.out.println("關(guān)注公眾號(hào):撿田螺的小男孩");
關(guān)注公眾號(hào):撿田螺的小男孩
8. try-with-resources的改進(jìn)
JDK 9對(duì)try-with-resources異常處理機(jī)制進(jìn)行了升級(jí)~
//JDK?7,8
try?(BufferedReader?br?=?new?BufferedReader(new?FileReader("d:七里香.txt"))?{
???br.readLine();
}catch(IOException?e){
??log.error("IO?異常,e:{}",e);
}
//JDk?9
BufferedReader?br?=?new?BufferedReader(new?FileReader("d:七里香.txt")
try(br){
??br.readLine();
}catch(IOException?e){
??log.error("IO?異常,e:{}",e);
}
9. Stream API的改進(jìn)
JDK 9 為Stream API引入以下這些方法,豐富了流處理操作:
takeWhile() dropWhile() iterate ofNullable
「takeWhile」
使用一個(gè)斷言(Predicate 接口)作為參數(shù),返回給定Stream的子集直到斷言語(yǔ)句第一次返回 false
//?語(yǔ)法格式
default?Stream?takeWhile(Predicate?super?T>?predicate)
//代碼示例
Stream.of(1,2,3).takeWhile(s->?x<2)
?????????.forEach(System.out::println);?
?//輸出
?1
「dropWhile」
與 takeWhile()作用相反,使用一個(gè)斷言(Predicate 接口)作為參數(shù),直到斷言語(yǔ)句第一次返回true,返回給定Stream的子集
//語(yǔ)法
default?Stream?dropWhile(Predicate?super?T>?predicate)
//代碼示例
Stream.of(1,2,3).dropWhile(s->?x<2)
?????????.forEach(System.out::println);
//輸出
2
3
「iterate」
iterate() 方法能夠返回以seed(第一個(gè)參數(shù))開(kāi)頭,匹配 Predicate(第二個(gè)參數(shù))直到返回false,并使用第三個(gè)參數(shù)生成下一個(gè)元素的元素流。
//語(yǔ)法
static??Stream?iterate(T?seed,?Predicate?super?T>?hasNext,?UnaryOperator?next)
//代碼示例
IntStream.iterate(2,?x?->?x?10,?x?->?x*x).forEach(System.out::println);
//輸出
2
4
「ofNullable」
如果指定元素為非null,則獲取一個(gè)元素并生成單個(gè)元素流,元素為null則返回一個(gè)空Stream。
//語(yǔ)法
static??Stream?ofNullable(T?t)
//代碼示例
Stream?s1=?Stream.ofNullable(100);
s1.forEach(System.out::println)
Stream?s2?=?Stream.ofNullable(null);
s2.forEach(System.out::println)
//輸出
100
10.其他
??
HTTP 2客戶端 (支持 WebSocket和 HTTP2 流以及服務(wù)器推送) 進(jìn)程API(控制和管理操作系統(tǒng)進(jìn)程) String底層存儲(chǔ)結(jié)構(gòu)更改(char[]替換為byte[]) 標(biāo)識(shí)符添加限制( String _ ="hello"不能用) 響應(yīng)式流 API (支持Java 9中的響應(yīng)式編程)
Java 10 新特性

1.局部變量類(lèi)型推斷
JDK 10增加了局部變量類(lèi)型推斷(Local-Variable Type Inference)功能,讓 Java 可以像Js里的var一樣可以自動(dòng)推斷數(shù)據(jù)類(lèi)型。Java中的var是一個(gè)保留類(lèi)型名稱,而不是關(guān)鍵字。
JDK 10之前
List?list?=?new?ArrayList();
Stream?stream?=?Stream.of(1,?2,?3);
JDK 10 之后
var?list?=?new?ArrayList();?//?ArrayList
var?stream?=??Stream.of(1,?2,?3);
var 變量類(lèi)型推斷的使用也有局限性,僅「局限」于以下場(chǎng)景:
具有初始化器的局部變量 增強(qiáng)型for循環(huán)中的索引變量 傳統(tǒng)for循環(huán)中聲明的局部變量
而「不能用于」
推斷方法的參數(shù)類(lèi)型 構(gòu)造函數(shù)參數(shù)類(lèi)型推斷 推斷方法返回類(lèi)型 字段類(lèi)型推斷 捕獲表達(dá)式
2. 不可變集合的改進(jìn)
JDK 10中,List,Set,Map 提供了一個(gè)新的靜態(tài)方法copyOf(Collection extends E> coll),它返回Collection集合一個(gè)不可修改的副本。
JDK 源碼:
static??List?copyOf(Collection?extends?E>?coll)?{
????return?ImmutableCollections.listCopy(coll);
}
使用實(shí)例:
var?oldList?=?new?ArrayList();
oldList.add("歡迎關(guān)注公眾號(hào):");
oldList.add("撿田螺的小男孩");
var?copyList?=?List.copyOf(oldList);
oldList.add("在看、轉(zhuǎn)載、點(diǎn)贊三連");?
copyList.add("雙擊666");??//UnsupportedOperationException異常
3. 并行全垃圾回收器 G1
?JDK 9引入 G1 作為默認(rèn)垃圾收集器,執(zhí)行GC 時(shí)采用的是基于單線程標(biāo)記掃描壓縮算法(mark-sweep-compact)。為了最大限度地減少 Full GC 造成的應(yīng)用停頓的影響,Java 10 中將為 G1 引入多線程并行 GC,同時(shí)會(huì)使用與年輕代回收和混合回收相同的并行工作線程數(shù)量,從而減少了 Full GC 的發(fā)生,以帶來(lái)更好的性能提升、更大的吞吐量。
?
4. 線程本地握手
Java 10 中線程管控引入JVM安全點(diǎn)的概念,將允許在不運(yùn)行全局JVM安全點(diǎn)的情況下實(shí)現(xiàn)線程回調(diào),由線程本身或者JVM線程來(lái)執(zhí)行,同時(shí)保持線程處于阻塞狀態(tài),這將會(huì)很方便使得停止單個(gè)線程或不停止線程成為可能。
5. Optional新增orElseThrow()方法
Optional、OptionalDouble等類(lèi)新增一個(gè)方法orElseThrow(),在沒(méi)有值時(shí)拋出異常
6. 其他新特性
基于 Java 的 實(shí)驗(yàn)性 JIT 編譯器 類(lèi)數(shù)據(jù)共享 Unicode 語(yǔ)言標(biāo)簽擴(kuò)展 根證書(shū) 基于時(shí)間(Time-Based)的版本控制模型
Java 11 新特性

1.字符串操作
String類(lèi)是Java最常用的類(lèi),JDK 11增加了一系列好用的字符串處理方法
isBlank() 判空。 strip() 去除首尾空格 stripLeading() 去除字符串首部空格 stripTrailing() 去除字符串尾部空格 lines() 分割獲取字符串流。 repeat() 復(fù)制字符串
//?判斷字符串是否為空白
"??".isBlank();????//?true
//?去除首尾空格
"?jay?".strip();??//?"jay"
//?去除首部空格?
"?jay?".stripLeading();???//?"jay?"
去除字符串尾部空格
"?jay?".stripLeading();???//?"?jay"
//?行數(shù)統(tǒng)計(jì)
"a\nb\nc".lines().count();????//?3
//?復(fù)制字符串
"jay".repeat(3);???//?"jayjayjay"
2.用于 Lambda 參數(shù)的局部變量語(yǔ)法
局部變量類(lèi)型推斷是Java 10引入的新特性,但是不能在Lambda 表達(dá)式中使用。Java 11再次創(chuàng)新,它允許開(kāi)發(fā)者在 Lambda 表達(dá)式中使用 var 進(jìn)行參數(shù)聲明。
var?map?=?new?HashMap();
map.put("公眾號(hào)",?"撿田螺的小男孩");
map.forEach((var?k,?var?v)?->?{
????System.out.println(k?+?":?"?+?v);
});
3.標(biāo)準(zhǔn)化HTTP Client
Java 9 引入Http Client API,Java 10對(duì)它更新,Java 11 對(duì)它進(jìn)行標(biāo)準(zhǔn)化。這幾個(gè)版本后,Http Client幾乎被完全重寫(xiě),支持HTTP/1.1和HTTP/2 ,也支持 websockets。
HttpClient?client?=?HttpClient.newHttpClient();
HttpRequest?request?=?HttpRequest.newBuilder()
????????????.uri(URI.create("https://github.com/whx123/JavaHome"))
????????????.GET()
????????????.build();
//?同步
HttpResponse?response?=?client.send(request,?HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
//?異步
client.sendAsync(request,?HttpResponse.BodyHandlers.ofString())
????.thenApply(HttpResponse::body)
????.thenAccept(System.out::println);
4. 單個(gè)命令編譯運(yùn)行源代碼
Java 11增強(qiáng)了Java 啟動(dòng)器,使之能夠運(yùn)行單一文件的Java 源代碼。
Java 11之前,要運(yùn)行一個(gè) Java 源代碼必須先編譯,再運(yùn)行
//?編譯
javac?Jay.java
//?運(yùn)行
java?Jay
Java 11之后,只要一個(gè)java命令就搞定
java?Jay.java
5. ZGC:可伸縮低延遲垃圾收集器
ZGC ,即 Z Garbage Collector(垃圾收集器或垃圾回收器)。它是一個(gè)可伸縮的、低延遲的垃圾收集器。 ZGC 主要為了滿足如下目標(biāo)進(jìn)行設(shè)計(jì):
GC 停頓時(shí)間不超過(guò) 10ms 既能處理幾百 MB 的小堆,也能處理幾個(gè) TB 的大堆 應(yīng)用吞吐能力不會(huì)下降超過(guò) 15%(與 G1 回收算法相比) 方便在此基礎(chǔ)上引入新的 GC 特性和利用 colord 針以及 Load barriers 優(yōu)化奠定基礎(chǔ) 當(dāng)前只支持 Linux/x64 位平臺(tái)
6.其他一些特性
添加 Epsilon 垃圾收集器。 支持 TLS 1.3 協(xié)議 飛行記錄器分析工具 動(dòng)態(tài)類(lèi)文件常量 低開(kāi)銷(xiāo)的 Heap Profiling
Java 12 新特性

1. Switch 表達(dá)式擴(kuò)展(預(yù)覽功能)
傳統(tǒng)的switch語(yǔ)句,容易漏寫(xiě)break而出錯(cuò),同時(shí)寫(xiě)法并不簡(jiǎn)潔優(yōu)雅。
Java 12之前
switch?(day)?{
????case?MONDAY:
????case?FRIDAY:
????case?SUNDAY:
????????System.out.println(6);
????????break;
????case?TUESDAY:
????????System.out.println(7);
????????break;
????case?THURSDAY:
????case?SATURDAY:
????????System.out.println(8);
????????break;
????case?WEDNESDAY:
????????System.out.println(9);
????????break;
}
JDk 12 之后,Switch表達(dá)式得到增強(qiáng),能接受語(yǔ)句和表達(dá)式。
switch?(day)?{
????case?MONDAY,?FRIDAY,?SUNDAY?->?System.out.println(6);
????case?TUESDAY????????????????->?System.out.println(7);
????case?THURSDAY,?SATURDAY?????->?System.out.println(8);
????case?WEDNESDAY??????????????->?System.out.println(9);
}
2. 緊湊的數(shù)據(jù)格式
JDK 12 新增了NumberFormat對(duì)復(fù)雜數(shù)字的格式化
NumberFormat?numberFormat?=?NumberFormat.getCompactNumberInstance(Locale.CHINA,?NumberFormat.Style.SHORT);
System.out.println(numberFormat.format(100000));
//output
10萬(wàn)
3. 字符串支持transform、indent操作
transform 字符串轉(zhuǎn)換,可以配合函數(shù)式接口Function一起使用
List?list1?=?List.of("jay",?"?撿田螺的小男孩");
List?list2?=?new?ArrayList<>();
list1.forEach(element?->
????????????list2.add(element.transform(String::strip)
????????????????????.transform((e)?->?"Hello,"?+?e))
????);
list2.forEach(System.out::println);
//輸出
Hello,jay
Hello,撿田螺的小男孩
indent 縮進(jìn),每行開(kāi)頭增加空格space和移除空格
String?result?=?"Java\n?Python\nC".indent(3);
System.out.println(result);
//輸出
???Java
????Python
???C
4. Files.mismatch(Path, Path)
Java 12 新增了mismatch方法,此方法返回第一個(gè)不匹配的位置,如果沒(méi)有不匹配,則返回 -1L。
public?static?long?mismatch(Path?path,?Path?path2)?throws?IOException;
代碼示例:
Path?file1?=?Paths.get("c:\\jay.txt");
Path?file2?=?Paths.get("c:\\撿田螺的小男孩.txt");
try?{
?long?fileMismatch?=?Files.mismatch(file1,?file2);
?System.out.println(fileMismatch);
}?catch?(IOException?e)?{
?e.printStackTrace();
}
5. Teeing Collector
Teeing Collector 是 Streams API 中引入的新的收集器實(shí)用程序,它的作用是 merge 兩個(gè) collector 的結(jié)果,API格式如下:
public?static?
????Collector?teeing(Collector?super?T,??,?R1>?downstream1,
????Collector?super?T,??,?R2>?downstream2,
????BiFunction?super?R1,???super?R2,?R>?merger)
直接看代碼例子吧,如下為求學(xué)生的平均分和總分的例子
??List?studentList=?Arrays.asList(
????????????????new?Student("jay",?90),
????????????????new?Student("撿田螺的小男孩",?100),
????????????????new?Student("撿表情的小男孩",?80)
????????);
????????String?teeingResult=studentList.stream().collect(
????????????????Collectors.teeing(
????????????????????????Collectors.averagingInt(Student::getScore),
????????????????????????Collectors.summingInt(Student::getScore),
????????????????????????(s1,s2)->?s1+?":"+?s2
????????????????)
????????);
?System.out.println(teeingResult);?//90:270
6.其他特性
支持unicode 11(684個(gè)新字符、11個(gè)新blocks、7個(gè)新腳本) JVM 常量 API (主要在新的java.lang.invoke.constant包中定義了一系列基于值的符號(hào)引用類(lèi)型,能夠描述每種可加載常量。) Shenandoah GC(低暫停時(shí)間垃圾收集器) G1 收集器提升 (可中止的混合收集集合、及時(shí)返回未使用的已分配內(nèi)存) 默認(rèn)CDS檔案 JMH 基準(zhǔn)測(cè)試
Java 13 新特性

Switch 表達(dá)式擴(kuò)展(引入 yield 關(guān)鍵字)
傳統(tǒng)的switch:
private?static?String?getText(int?number)?{
????String?result?=?"";
????switch?(number)?{
????????case?1,?2:
????????result?=?"one?or?two";
????????break;
????????case?3:
????????result?=?"three";
????????break;
????????case?4,?5,?6:
????????result?=?"four?or?five?or?six";
????????break;
????????default:
????????result?=?"unknown";
????????break;
Java 13之后,value break 語(yǔ)句不再被編譯,而是用 yield 來(lái)進(jìn)行值返回
private?static?String?getText(int?number)?{
????return?switch?(number)?{
????????case?1,?2:
????????????yield?"one?or?two";
????????case?3:
????????????yield?"three";
????????case?4,?5,?6:
????????????yield?"four?or?five?or?six";
????????default:
????????????yield?"unknown";
????};
}
2.文本塊升級(jí)
Java 13之前,字符串不能夠多行使用,需要通過(guò)換行轉(zhuǎn)義或者換行連接符等等,反正就是好麻煩、好難維護(hù)。
String?html?=?"\n"?+
??????????????"????\n"?+
??????????????"????????Hello,?撿田螺的小男孩
\n"?+
??????????????"????\n"?+
??????????????"\n";
Java 13之后,清爽多了~
String?html?=?"""
????????????????
????????????????????
????????????????????????Hello,??撿田螺的小男孩
????????????????????
????????????????
????????????????""";
3. SocketAPI 重構(gòu)
傳統(tǒng)的Java Socket API(java.net.ServerSocket 和 java.net.Socket)依賴于SocketImpl 的內(nèi)部實(shí)現(xiàn) 在 Java 13之前,通過(guò)使用 PlainSocketImpl 作為 SocketImpl 的具體實(shí)現(xiàn)。 Java 13 中的新底層實(shí)現(xiàn),引入 NioSocketImpl 的實(shí)現(xiàn)用以替換 SocketImpl 的 PlainSocketImpl 實(shí)現(xiàn),此實(shí)現(xiàn)與 NIO(新 I/O)實(shí)現(xiàn)共享相同的內(nèi)部基礎(chǔ)結(jié)構(gòu),并且與現(xiàn)有的緩沖區(qū)高速緩存機(jī)制集成在一起。
一個(gè)Socket簡(jiǎn)單例子:
import?java.io.IOException;
import?java.net.ServerSocket;
import?java.net.Socket;
public?class?SocketAPITest?{
????public?static?void?main(String[]?args)?{
????????try?(ServerSocket?serverSocket?=?new?ServerSocket(8080)){
????????????boolean?runFlag?=?true;
????????????while(runFlag){
????????????????Socket?clientSocket?=?serverSocket.accept();
????????????????//搞事情
????????????}
????????}?catch?(IOException?e)?{
????????????e.printStackTrace();
????????}
????}
}
運(yùn)行以上的實(shí)例,看下是否有以下關(guān)鍵詞輸出~
[class,load]?sun.nio.ch.NioSocketImpl
4.FileSystems.newFileSystem新方法
FileSystems 類(lèi)中添加了以下三種新方法,以便更容易地使用將文件內(nèi)容視為文件系統(tǒng)的文件系統(tǒng)提供程序:
1、newFileSystem(Path) 2、newFileSystem(Path, Map ) 3、newFileSystem(Path, Map , ClassLoader)
5. 增強(qiáng) ZGC 釋放未使用內(nèi)存
ZGC 是Java 11 中引入的最為矚目的垃圾回收特性,是一種可伸縮、低延遲的垃圾收集器。但是實(shí)際使用中,它不能夠主動(dòng)將未使用的內(nèi)存釋放給操作系統(tǒng)。 Java 13 中對(duì) ZGC 的改進(jìn),包括釋放未使用內(nèi)存給操作系統(tǒng)、支持最大堆大小為 16TB、JVM參數(shù)-XX:SoftMaxHeapSize 來(lái)軟限制堆大小
6.其他特性
動(dòng)態(tài) CDS 存檔, 擴(kuò)展了 Java 10 中引入的類(lèi)數(shù)據(jù)共享功能, 使用CDS 存檔變得更容易。 文本塊的字符串類(lèi)新方法,如formatted(Object…args),stripIndent()等。
Java 14 新特性

1. instanceof模式匹配
instanceof 傳統(tǒng)使用方式:
if?(person?instanceof?Singer)?{
????Singer?singer?=?(Singer)?person;
????singer.sing();
}?else?if?(person?instanceof?Writer)?{
????Writer?writer?=?(Writer)?person;
????writer.write();
}
Java 14 對(duì) instanceof 進(jìn)行模式匹配改進(jìn)之后
if?(person?instanceof?Singer?singer)?{
????singer.sing();
}?else?if?(person?instanceof?Writer?writer)?{
???writer.write();
}
2.Record 類(lèi)型(預(yù)覽功能)
Java 14將Record 類(lèi)型作為預(yù)覽特性而引入,有點(diǎn)類(lèi)似于Lombok 的@Data注解,看個(gè)例子吧:
public?record?Person(String?name,?int?age)?{
????public?static?String?address;
????public?String?getName()?{
????????return?name;
????}
}
反編譯結(jié)果:
public?final?class?Person?extends?java.lang.Record?{
????private?final?java.lang.String?name;
????private?final?java.lang.String?age;
????public?Person(java.lang.String?name,?java.lang.String?age)?{?/*?compiled?code?*/?}
????public?java.lang.String?getName()?{?/*?compiled?code?*/?}
????public?java.lang.String?toString()?{?/*?compiled?code?*/?}
????public?final?int?hashCode()?{?/*?compiled?code?*/?}
????public?final?boolean?equals(java.lang.Object?o)?{?/*?compiled?code?*/?}
????public?java.lang.String?name()?{?/*?compiled?code?*/?}
????public?java.lang.String?age()?{?/*?compiled?code?*/?}
}
可以發(fā)現(xiàn),當(dāng)用 Record 來(lái)聲明一個(gè)類(lèi)時(shí),該類(lèi)將自動(dòng)擁有下面特征:
構(gòu)造方法 hashCode() 方法 euqals() 方法 toString() 方法 類(lèi)對(duì)象被final 關(guān)鍵字修飾,不能被繼承。
3. Switch 表達(dá)式-標(biāo)準(zhǔn)化
switch 表達(dá)式在之前的 Java 12 和 Java 13 中都是處于預(yù)覽階段,終于在 Java 14 標(biāo)準(zhǔn)化,成為穩(wěn)定版本。
Java 12 為switch 表達(dá)式引入Lambda 語(yǔ)法 Java 13 使用yield代替 break 關(guān)鍵字來(lái)返回表達(dá)式的返回值。
String?result?=?switch?(day)?{
????case?"M",?"W",?"F"?->?"MWF";
????case?"T",?"TH",?"S"?->?"TTS";
????default?->?{
????????if?(day.isEmpty())?{
????????????yield?"Please?insert?a?valid?day.";
????????}?else?{
????????????yield?"Looks?like?a?Sunday.";
????????}
????}
};
System.out.println(result);
4. 改進(jìn) NullPointerExceptions提示信息
Java 14 之前:
String?name?=?song.getSinger().getSingerName()
?
//堆棧信息
Exception?in?thread?"main"?java.lang.NullPointerException
????at?NullPointerExample.main(NullPointerTest.java:6)
Java 14,通過(guò)引入JVM 參數(shù)-XX:+ShowCodeDetailsInExceptionMessages,可以在空指針異常中獲取更為詳細(xì)的調(diào)用信息。
Exception?in?thread?"main"?java.lang.NullPointerException:?Cannot?invoke?"Singer.getSingerName()"?
because?the?return?value?of?"rainRow.getSinger()"?is?null
????at?NullPointerExample.main(NullPointerTest.java:6)
5. 其他特性
G1 的 NUMA 可識(shí)別內(nèi)存分配 刪除 CMS 垃圾回收器 GC 支持 MacOS 和 Windows 系統(tǒng)
Java 15 新特性


1.EdDSA 數(shù)字簽名算法
使用 Edwards-Curve 數(shù)字簽名算法(EdDSA)實(shí)現(xiàn)加密簽名。 與其它簽名方案相比,EdDSA 具有更高的安全性和性能。 得到許多其它加密庫(kù)(如 OpenSSL、BoringSSL)的支持。
2.Sealed Classes(封閉類(lèi),預(yù)覽)
封閉類(lèi),可以是封閉類(lèi)、封閉接口,防止其他類(lèi)或接口擴(kuò)展或?qū)崿F(xiàn)它們。
public?abstract?sealed?class?Singer
????permits?Jay,?Eason{
????...
}
類(lèi)Singer被sealed 修飾,是封閉類(lèi),只能被2個(gè)指定子類(lèi)(Jay, Eason)繼承。
3. Hidden Classes(隱藏類(lèi))
隱藏類(lèi)天生為框架設(shè)計(jì)的。 隱藏類(lèi)只能通過(guò)反射訪問(wèn),不能直接被其他類(lèi)的字節(jié)碼。
4. Remove the Nashorn JavaScript Engine
Nashorn太難維護(hù)了,移除 Nashorn JavaScript引擎成為一種必然 其實(shí)早在JDK 11 中就已經(jīng)被標(biāo)記為 deprecated 了。
5.Reimplement the Legacy DatagramSocket API(重新實(shí)現(xiàn)DatagramSocket API)
重新實(shí)現(xiàn)老的DatagramSocket API 更改java.net.DatagramSocket 和 java.net.MulticastSocket 為更加簡(jiǎn)單、現(xiàn)代化的底層實(shí)現(xiàn)。
6.其他
Disable and Deprecate Biased Locking(準(zhǔn)備禁用偏向鎖) instanceof 自動(dòng)匹配模式(預(yù)覽) ZGC,一個(gè)可伸縮、低延遲的垃圾回收器。(轉(zhuǎn)正) Text Blocks,文本功能轉(zhuǎn)正(JDK 13和14預(yù)覽,14終于轉(zhuǎn)正) Remove the Solaris and SPARC Ports(刪除 Solaris 和 SPARC 端口) 外部存儲(chǔ)器訪問(wèn) API(允許Java 應(yīng)用程序安全有效地訪問(wèn) Java 堆之外的外部?jī)?nèi)存。) Record類(lèi)型二次預(yù)覽(在Java 14就預(yù)覽過(guò)啦)
參考與感謝
JDK6 新特性[1] Java 7的新功能[2] Java 9 新特性概述[3] Java 9 新特性[4] Java 10 新特性介紹[5] Java 11 新特性介紹[6] Java 13 新特性概述[7] Java 14 新特性概述[8] JDK/Java 15發(fā)布 Java 15 正式發(fā)布, 14 個(gè)新特性,刷新你的認(rèn)知!!
Reference
JDK6 新特性: https://blog.csdn.net/weixin_40926603/article/details/84970283
[2]Java 7的新功能: https://stackoverflow.com/questions/213958/new-features-in-java-7
[3]Java 9 新特性概述: https://developer.ibm.com/zh/articles/the-new-features-of-Java-9/
[4]Java 9 新特性: https://www.runoob.com/java/java9-new-features.html
[5]Java 10 新特性介紹: https://developer.ibm.com/zh/technologies/java/articles/the-new-features-of-java-10/
[6]Java 11 新特性介紹: https://developer.ibm.com/zh/technologies/java/articles/the-new-features-of-java-11/
[7]Java 13 新特性概述: https://developer.ibm.com/zh/technologies/java/articles/the-new-features-of-java-13/
[8]Java 14 新特性概述: https://developer.ibm.com/zh/technologies/java/articles/the-new-features-of-java-14/
點(diǎn)個(gè)?在看?
