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