最近,有许多人在传说 SpringBoot要出3.0的版别了,并且宣告不再支撑 Java 8,最低要求是 Java 17了。

其实,早在2021年9月份,关于 Spring Framework 6.0的音讯出来的时分,Spring 官方就已经清晰了不会向下兼容,最低的 JDK 版别是 JDK 17。

Jdk17新特性及未来发展趋势

2022年,Spring Framework 6.0和 SpringBoot 3.0都会推出,在此之前,Java社区很坚硬,一直是”新版任你发,我用Java 8″,不论新版别怎么出,很少有人乐意升级。

这一次,Spring 直接来了个大招,跨过 JDK 8-16,直接升级到 JDK 17 ,不知道会对 Java生态发生怎样的影响。

为什么是 Java 17

这么多新版别的 JDK,并且2022年还会推出 JDK 18 和 JDK 19,为什么 Spring 选择了 JDK 17呢。

主要是因为他是一个 LTS版别,所谓 LTS,是 Long Term Support,也就是官方确保会长时间支撑的版别。

从 JDK 诞生到现在,还在长时间支撑的版别主要有 JDK 7、JDK 8 、JDK 11以及 JDK 17

Jdk17新特性及未来发展趋势

这一次 Spring直接跨越了 JDK 11,升级到 JDK 17,主要的考虑应该是因为JDK 17有更多的新特性支撑。

接下来咱们介绍几个新特性,这些新特性都是咱们开发者息息相关的,或许说是会影响咱们写代码的。

JDK 17 支撑的新特性

这儿所谓的新特性,不仅仅 JDK 17中新增的,而是 JDK 17和 JDK 8相比,新增的特性。

本地变量类型揣度

在Java 10之前版别中,咱们想界说界说局部变量时。咱们需求在赋值的左侧供给显式类型,并在赋值的右边供给完成类型:

MyObjectvalue=newMyObject();

在Java 10中,供给了本地变量类型揣度的功用,能够经过var声明变量:

varvalue=newMyObject();

本地变量类型揣度将引进“var”关键字,而不需求显式的标准变量的类型。

其实,所谓的本地变量类型揣度,也是Java 10供给给开发者的语法糖。

虽然咱们在代码中运用var进行了界说,但是关于虚拟机来说他是不认识这个var的,在java文件编译成class文件的进程中,会进行解糖,运用变量实在的类型来代替var(详细信息能够参阅:我反编译了Java 10的本地变量类型揣度)

Switch 表达式

在JDK 12中引进了Switch表达式作为预览特性。并在Java 13中修改了这个特性,引进了yield句子,用于返回值。

而在之后的Java 14中,这一功用正式作为标准功用供给出来。

在曾经,咱们想要在switch中返回内容,仍是比较麻烦的,一般语法如下:

inti;switch(x){case"1":i=1;break;case"2":i=2;break;default:i=x.length();break;}

在JDK13中运用以下语法:

inti=switch(x){case"1"->1;case"2"->2;default->{intlen=args[1].length();yieldlen;}};

或许

inti=switch(x){case"1":yield1;case"2":yield2;default:{intlen=args[1].length();yieldlen;}};

在这之后,switch中就多了一个关键字用于跳出switch块了,那就是yield,他用于返回一个值。

和return的差异在于:return会直接跳出当时循环或许办法,而yield只会跳出当时switch块。

Text Blocks

Java 13中供给了一个Text Blocks的预览特性,并且在Java 14中供给了第二个版别的预览。

text block,文本块,是一个多行字符串文字,它避免了对大多数转义序列的需求,以可预测的办法主动格式化字符串,并在需求时让开发人员控制格式。

咱们曾经从外部copy一段文本串到Java中,会被主动转义,如有一段以下字符串:

<html><body><p>Hello,world</p></body></html>

将其复制到Java的字符串中,会展现成以下内容:

"<html>\n"+"<body>\n"+"<p>Hello,world</p>\n"+"</body>\n"+"</html>\n";

即被主动进行了转义,这样的字符串看起来不是很直观,在JDK 13中,就能够运用以下语法了:

"""<html><body><p>Hello,world</p></body></html>""";

运用“”“作为文本块的开端符和结束符,在其中就能够放置多行的字符串,不需求进行任何转义。看起来就非常清爽了。

如常见的SQL句子:

Stringquery="""SELECT`EMP_ID`,`LAST_NAME`FROM`EMPLOYEE_TB`WHERE`CITY`='INDIANAPOLIS'ORDERBY`EMP_ID`,`LAST_NAME`;""";

看起来就比较直观,清爽了。

Records

Java 14 中便包含了一个新特性:EP 359: Records,

Records的目标是扩展Java言语语法,Records为声明类供给了一种紧凑的语法,用于创立一品种中是“字段,仅仅字段,除了字段什么都没有”的类。

经过对类做这样的声明,编译器能够经过主动创立一切办法并让一切字段参与hashCode()等办法。这是JDK 14中的一个预览特性。

运用record关键字能够界说一个记载:

recordPerson(StringfirstName,StringlastName){}

record 解决了运用类作为数据包装器的一个常见问题。纯数据类从几行代码显著地简化为一行代码。(详见:Java 14 发布了,不运用”class”也能界说类了?还顺手要干掉Lombok!)

封闭类

在Java 15之前,Java认为”代码重用”始终是一个终极目标,所以,一个类和接口都能够被任意的类完成或承继。

但是,在许多场景中,这样做是简单造成错误的,并且也不符合物理国际的实在规则。

例如,假设一个业务领域只适用于轿车和卡车,而不适用于摩托车。

在Java中创立Vehicle抽象类时,应该只允许Car和Truck类扩展它。

经过这种办法,咱们希望确保在域内不会呈现误用Vehicle抽象类的状况。

为了解决相似的问题,在Java 15中引进了一个新的特性——密闭。

想要界说一个密闭接口,能够将sealed修饰符应用到接口的声明中。然后,permit子句指定允许完成密闭接口的类:

publicsealedinterfaceServicepermitsCar,Truck{}

以上代码界说了一个密闭接口Service,它规则只能被Car和Truck两个类完成。

与接口相似,咱们能够经过运用相同的sealed修饰符来界说密闭类:

publicabstractsealedclassVehiclepermitsCar,Truck{}

经过密闭特性,咱们界说出来的Vehicle类只能被Car和Truck承继。

instanceof 形式匹配

instanceof是Java中的一个关键字,咱们在对类型做强制转换之前,会运用instanceof做一次判别,例如:

if(animalinstanceofCat){Catcat=(Cat)animal;cat.miaow();}elseif(animalinstanceofDog){Dogdog=(Dog)animal;dog.bark();}

Java 14带来了改进版的instanceof操作符,这意味着咱们能够用更简练的办法写出之前的代码例子:

if(animalinstanceofCatcat){cat.miaow();}elseif(animalinstanceofDogdog){dog.bark();}

咱们都不难发现这种写法大大简化了代码,省掉了显式强制类型转换的进程,可读性也大大提高了。

switch 形式匹配

根据instanceof形式匹配这个特性,咱们能够运用如下办法来对对象o进行处理:

staticStringformatter(Objecto){Stringformatted="unknown";if(oinstanceofIntegeri){formatted=String.format("int%d",i);}elseif(oinstanceofLongl){formatted=String.format("long%d",l);}elseif(oinstanceofDoubled){formatted=String.format("double%f",d);}elseif(oinstanceofStrings){formatted=String.format("String%s",s);}returnformatted;}

能够看到,这儿运用了许多if-else,其实,Java中给咱们供给了一个多路比较的工具,那就是switch,并且从Java 14开端支撑switch表达式,但switch的功用一直都是非常有限的。

在Java 17中,Java的工程师们扩展了switch句子和表达式,使其能够适用于任何类型,并允许case标签中不仅带有变量,还能带有形式匹配。咱们就能够更清楚、更可靠地重写上述代码,例如:

staticStringformatterPatternSwitch(Objecto){returnswitch(o){caseIntegeri->String.format("int%d",i);caseLongl->String.format("long%d",l);caseDoubled->String.format("double%f",d);caseStrings->String.format("String%s",s);default->o.toString();};}

能够看到,以上的switch处理的是一个Object类型,并且case中也不再是精确的值匹配,而是形式匹配了。

总结

以上,咱们介绍了几个从 JDK 9开端,一直到 JDK 17中的几个能够改动咱们写代码的办法的新特性。其实,很多的版别中,还有一些其他的特性及优化,咱们没有在这儿一一打开。

大家感兴趣的能够到 JDK 官网检查各个版别的新功用介绍。

随着 Spring Framework 6 和 SpringBoot 3.0的推出,信任会有一些公司在新项目中选用新版别,那么 JDK 17势必要被应用到生产环境中。

以上这些特性,大多数都是对开发比较友好的,有时机的话能够应用起来。