JAVA8~17新特性
目錄
一、前言
二、JAVA8
Lambda表達式
Stream API
創建方式
中間操作
終止操作
Optional類
三、JAVA9
模塊機制
JShell交互式編程
?
接口
新增集合工廠方法
四、JAVA10
局部變量類型判斷
五、JAVA11
Lambda表達式補充
String方法的補充
全新的HttpClient 使用
六、JAVA12-16
新的switch語法
文本塊
新的instanceof語法
空指針異常的改進
記錄類型(record)
七、Java 17
密封類型(sealed關鍵字)
總結
一、前言
springboot3 最低dk17,java8估計要被棄用了
二、JAVA8
Lambda表達式
相當于匿名內部類的簡寫
public void test() {Thread t1 = new Thread(()-> System.out.println("你好")); //lambda 表達式 t1.start();}規范:
????????(名稱)-> {代碼語句,包括返回值}
????????和匿名內部類不同,只支持接口,不支持抽象類
????????接口有且只有一個抽象方法
????????接口上有@FunctionalInterface 標識
自定義接口
@FunctionalInterface public interface myBy {Integer getAdd(Integer a,Integer b);}? ? ? ?
使用
public void test02() {myBy myBy=(a,b)-> a+b; //實現接口System.out.println(myBy.getAdd(1,2));}有現成的實現可以直接代替
private static Integer Add(Integer a, Integer b){ //加法return a+b;}public void test02() {// myBy myBy=(a,b)-> a+b; myBy my=(OneTest::Add); //借用別人的實現方法System.out.println(myBy.getAdd(1,2));}線程安全性,(十分局限,不允許對外部數據進行賦值操作)
錯誤案例
List<Integer> list=Arrays.asList(1,1,23,23,456,9,9,12,678,23); Integer a=0; list.forEach(i->{a+=i; //請注意,這個寫法是錯誤的,lambda表達式為了保證線程安全不允許對外部數據進行賦值操作,當前編譯階段就會報錯}); System.out.println(a);Stream API
函數式編程
作用:對集合、數組操作
對比Collections(集合操作工具類),Arrays(數組操作工具類) :
Collections和Arrays會改變原來的集合數據;Stream則不會,它會返回一個新的帶有結果的Stream;不想改變原有數據的情況下操作集合和數組可以使用Stream;操作集合和數組建議使用這種方式,進一步減少被優化的可能,能少寫for就少寫一個創建方式
public void test012() {List<Integer> list=Arrays.asList(1,23,456,12,678,23); // 順序流 按元素順序返回Stream<Integer> stream1 = list.stream(); // 并行流 ,同時取數據 Stream<Integer> stream2 = list.parallelStream(); //數組類型 int[] arr =new int[]{1,2,3,4,5}; IntStream stream3 = Arrays.stream(arr); Stream<Integer> integerStream = Stream.of(1, 2, 3, 4, 5); }//Math.random() 生成 [0,1)的 double數 //生成10個數 Stream.generate(Math::random).limit(10).forEach(System.out::println);中間操作
數據過濾(filter)
//數據過濾 保留大于10的數據 // 當filter(e->{return true;}) 返回true才保留當前操作數據 List<Integer> list=Arrays.asList(1,23,456,9,12,678,23); list.stream().filter(e->e>10).forEach(System.out::println); //結果 23,456,12,678,23截取片段(limit)
List<Integer> list=Arrays.asList(1,23,456,9,12,678,23); //獲得前4條數據 結果 1,23,456,9 list.stream().limit(4).forEach(System.out::println);舍棄片段(skip)(截取片段 相反)
List<Integer> list=Arrays.asList(1,23,456,9,12,678,23); //丟棄前面4個數據,結果為12,678,23 list.stream().skip(4).forEach(System.out::println);去重(distinct)
List<Integer> list=Arrays.asList(1,1,23,23,456,9,9,12,678,23); //去重 根據equals和hashCode, 結果為:1,23,456,9,12,678list.stream().distinct().forEach(System.out::println);映射(map)
自定義操作
map(e->{return "結果"}) 和filter類似, 只是return是自定義的結果
List<String> list=Arrays.asList("aa","bb","cc","dd");// 還是操作數據 ,自定義操作數據,用來返回一些特定數據; str.toUpperCase()轉化成大寫// map(e->{return "結果"}) 和filter類似 只是return是自定義的結果//結果 AA,BB,CC,DDlist.stream().map(str->str.toUpperCase()).forEach(System.out::println);排序(sorted)
List<Integer> list=Arrays.asList(1,1,23,23,456,9,9,12,678,23);// 自然排序 ,結果:1,1,9,9,12,23,23,23,456,678// 對類對象的排序需要實現 Comparable 接口list.stream().sorted().forEach(System.out::println);//自定義排序,即使是類對象也不用實現Comparable 接口//自定義排序結果為:687,456,23,23,23,12,9,9,1,1list.stream().sorted((a,b)->{return Integer.compare(b,a); }).forEach(System.out::println);終止操作
匹配與查找
allMatch(lambda) 檢查是所有元素滿足條件 anyMatch(lambda) 檢查是否至少匹配一個元素 noneMatch(lambda) 檢查是否沒有匹配的元素 findFirst() 返回第一個元素 findAny() 返回當前流中的任意元素 count() 返回流元素的總個數 max(Double::compare) 返回流中最大值 min(Double::compare)返回流中最小值 forEach(lambda) 內部迭代匹配與查找示例:
// 1、allMatch 驗證是否全部元素滿足條件 List<Integer> list=Arrays.asList(1,1,23,23,456,9,9,12,678,23); // 是否全部元素大于 30;返回false,true;當前結果為false boolean b = list.stream().allMatch(e -> e > 30); System.out.println(b);//2、noneMatch 檢查全部元素,是否全部不滿足條件 // 全部不滿足條件為true List<Integer> list=Arrays.asList(1,1,23,23,456,9,9,12,678,23); // 判斷全部元素是否沒有0,結果為true boolean b1 = list.stream().noneMatch(e -> e == 0); System.out.println(b1);//3、findFirst 返回第一個元素 // 當前結果為 1 List<Integer> list=Arrays.asList(1,1,23,23,456,9,9,12,678,23); Optional<Integer> first = list.stream().findFirst(); System.out.println(first);// 4、 findAny 隨機返回一個元素 List<Integer> list=Arrays.asList(1,1,23,23,456,9,9,12,678,23); // ?? 有BUG? 每次都是同一個結果 //Collections.shuffle(list); 還是洗牌好用Optional<Integer> first = list.stream().findAny();System.out.println(first);//5、count 求元素總數 // 結果為 10 List<Integer> list=Arrays.asList(1,1,23,23,456,9,9,12,678,23);long count = list.stream().count();System.out.println(count);//5、max最大值 自然排列取右邊值//最大值Optional<Integer> max = list.stream().max(Double::compare);//Optional<Integer> max = list.stream().max((a,b)->Double.compare(a,b));System.out.println(max.get());//6、最小值 自然排列取左邊值 Optional<Integer> min = list.stream().min(Double::compare); //Optional<Integer> min = list.stream().min((a,b)->Double.compare(a,b)); System.out.println(min.get());//7、遍歷// list.forEach(System.out::println); 集合自帶了遍歷list.stream().forEach(System.out::println);歸約(reduce)
// 計算結果,返回計算結果 // 0初始值,lambda累加操作 (a是初始值也是下一次結果值當前初始值設置是0,b是索引為i的元素) //結果為1235 Integer reduce = list.stream().reduce(0, (a, b) -> a + b);收集(collect)
把結果轉化為list或set等
// 把結果轉化為list List<Integer> list=Arrays.asList(1,1,23,23,456,9,9,12,678,23); List<Integer> collect = list.stream().filter(e -> e > 10).collect(Collectors.toList()); System.out.println(collect);//把結果轉化為set List<Integer> list=Arrays.asList(1,1,23,23,456,9,9,12,678,23); Set<Integer> collect = list.stream().filter(e -> e > 10).collect(Collectors.toSet()); System.out.println(collect);Optional類
可以預防空指針異常,
有if(a!=null) 時就優先使用這個類;
可以將任何一個類包裝進Optional類中
API方法:
//創建 Optional.of(A) // A必須非空,A為空會報錯 Optional.empty() //創建一個非空的Optional實例 Optional.ofNullable(A) //A可以為空 ,A為空不會報錯; 使用這個//返回數據 Optional.ofNullable(A).get() 返回包裝的A Optional.ofNullable(A).orElse(B) 當前A不為空就返回A,否則返回B,(A和B需要是同一個類型) Optional.ofNullable(A).orElseGet() 如果有值則返回,否則返回有接口實現提供的對象 Optional.ofNullable(A).orElseThrow() 如果有值則將其返回,否則拋出由Supplier接口實現提供的異常示例:
// 如果A為空就返回B String A=null; String a = Optional.ofNullable(A).orElse("A為空"); System.out.println(a);private static void hello(String str){Optional.ofNullable(str) //包裝進入Optional,空的也會放入 .ifPresent(i->{System.out.println(i); //打印 });}Optional不太方便,Lambda里面不能執行對外部屬性執行賦值操作還是挺多限制的不如使用Objects.isNull(A)
三、JAVA9
模塊機制
module-info.java文件
//暴露出去 module module.a {exports com.test; }// 只暴露給指定的模塊 module module.a {exports com.test to module.b; }//導入module.a 中暴露的內容 module module.b {requires module.a; }//依賴的傳遞性 module module.a {exports com.test;requires transitive java。logging; // 傳遞到引用的模塊 }//暴露出去,并且開放反射權限 open module module.a {exports com.test; }JShell交互式編程
?
接口
接口可以存在私有方法(私有方法必須要實現)
新增集合工廠方法
public void test04() {Map<String, Integer> map = Map.of("A", 1, "B", 2); //生成只讀map List<Integer> list = List.of(1, 2, 3, 4, 5); // 和Arrays.asList(1, 2, 3, 4, 5)一樣,生成只讀list //list.add(6); 錯誤 list是只讀的 System.out.println(map);}四、JAVA10
局部變量類型判斷
怎么變成js了,
public void test05() {var a="hello,word"; // 只能定義在方法局部變量 // var b; 錯誤,不能定義未賦值的變量 System.out.println(a);}五、JAVA11
Lambda表達式補充
內可以定義 var類型變量;
String方法的補充
public void test06() {String str=" "; System.out.println(str.isEmpty()); // 判斷內容是否為空(有空格也是false) System.out.println(str.isBlank()); //判斷外形是否為空(肉眼觀察,即使有空格也是true)// str.repeat(2) 重復拼接2次成新字符串// str.lines() 根據 \n分割//str.strip() 去除首位空格// str.stripLeading() 去除首部位空格// str.stripTrailing() 去除尾部空格}全新的HttpClient 使用
public void test07() throws URISyntaxException, IOException, InterruptedException {//創建 HttpClient client=HttpClient.newHttpClient(); //構建請求 HttpRequest request = HttpRequest.newBuilder(new URI("https://www.baidu.com")).GET().build(); HttpResponse<String> send = client.send(request, HttpResponse.BodyHandlers.ofString()); //發送請求 System.out.println(send.body()); }六、JAVA12-16
新的switch語法
老方式
private static String grade(int score){score/=10; String Gl=""; switch (score){case 10:case 9:Gl="優秀"; break; case 8:case 7:Gl="良好"; break; case 6:Gl="及格"; break; default:Gl="不及格"; }return Gl; }switch允許有返回值,不寫break
為switch表達式
private static String grade2(int score){score/=10; return switch (score){case 10,9->"優秀"; case 8,7->"良好"; case 6->"及格"; default->"不及格"; };}返回值yield
private static String grade2(int score){score/=10; return switch (score){case 10,9->{//可以執行其他邏輯 System.out.println("優秀"); yield "優秀"; }case 8,7->"良好"; case 6->"及格"; default->"不及格"; };}文本塊
public void test09() {// 普通字符串String str="adbc\nsdawd"; System.out.println(str); //文本塊 String str2=""" 文本塊內容: asaiddawjid "sdfsef"fsef mdkaslekf <a herf="fsdf"> """; System.out.println(str2);}新的instanceof語法
舊的用法a instanceof Atrue: a是A的實例或者 ,a是A類的后代 新補充:a instanceof A b為true時候相當于多執行了一步 A b=(A)a可以直接轉化對應的類型
//舊的寫法 @Override public boolean equals(Object obj) {if(obj ==this) return true; if (obj instanceof Student){Student test=(Student) obj; return test.name.equals(this.name);}return false; }//新寫法省一行代碼 @Override public boolean equals(Object obj) {if(obj ==this) return true; if (obj instanceof Student test){ // ture時候把obj轉化成 了(Student)testreturn test.name.equals(this.name); }return false;}空指針異常的改進
這個特性應該最容易感知出來(笑~)
有空指針異常時候打印的錯誤信息明確的指出了哪個參數空指針異常
記錄類型(record)
在編譯時候自動編譯出 get、hashcode、equals、toString等方法
支持實現接口,不支持繼承(位置已經被占用)
內部不能定義成員變量
//記錄類型 public record Account(String user,String pwd) {//private String adb; 錯誤,不能定義成員變量 //定義方法 public void Add(){System.out.println("調用Add"); } } //使用 public void test010() {Account account1=new Account("123","2334"); account1.Add(); System.out.println(account1); }七、Java 17
密封類型(sealed關鍵字)
以前final修飾的類不能被繼承
sealed 修飾的類可以定點繼承,只允許指定的類繼承
要求:
1、可以基于普通類、抽象類、接口也可以是繼承自其他抽象類的子類或是實現其他接口的類等 2、必須有子類繼承,且不能是匿名內部類或者是lambda的形式 3、sealed寫在原來final的位置,但是不能和final、non-selaled關鍵字同時出現,只能選擇其一 4、繼承的子類必須標記為final、sealed、non-sealed類型示例:
//A類 public sealed class A permits B { //只允許B繼承A (且B需要是final或者sealed 修飾的) public String name; }//B類 public non-sealed class B extends A {// B為final時候不允許其他類繼承 // B為sealed 允許指定類繼承 // B為B是non-sealed ,重新開放繼承權限,使其他類可以繼承B來間接繼承A ,(關鍵字怎么還帶個 - ,難看) } //C類 public class C extends B{ } // 測試 public void test011() {A a=new A(); B b=new B(); C c=new C(); //A是sealed ,B是non-sealed ,c依舊繼承了A中name屬性 c.name="王"; System.out.println(c.name);}總結
你還會繼續使用java8嗎?
總結
以上是生活随笔為你收集整理的JAVA8~17新特性的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: I LOVE CHINA
- 下一篇: 前端大型开源项目_在大型开源项目中管理问