女同事:哈哥,咱们之前用的java8,现在改用Java11,相比是有哪些新特性么? 我:哦,咱们是为了提高和其他子系统程序的兼容性稳定,才提高了JDK版本。 女同事:喔?那就是说你不知道有哪些新特性呗。 我:(??你们00后思路都这么清晰吗)咳咳,嗯,我只略知一二; 女同事:那你给我说说呗,我可想知道了呢 我:没问题走,先干饭去。(独门绝技:饭遁) 一提到JDK8的新特性,你可能就会联想到Lambda、函数式接口、Stream、Optional以及日期时间API增强等等; 诚然,这些都是我们日常在使用的特性了。然而你没在意的是JDK已经默默更新到JDK16了(平均6个月一版),并且在过几个月就JDK17了哈哈哈!唉,真是菜的令人头大。 前两天粉丝群的同学在分享面试题时,我看到面试题中包括:请说一下JDK8到JDK11都有哪些新特性?。我一惊,都卷成这吊样子了? 虽然我也在用JDK11然而我对新特性还停留在JDK8到底是我们老了还是卷不过年轻人了?下面是我总结各版本JDK的一些特性,看看你有哪些不知道吧。 本文我们梳理一些在日常编程中能用到的一些新特性,或许你会发现新大陆,赶快更新自己的代码吧当然,上线维护的代码尽量就别改了,你懂得。 JDK9(2017年9月)91、实例工厂方法 借助Java9的一项新功能,即集合工厂方法,我们可以轻松地使用预定义的数据创建不可变的集合。只需要在特定集合类型上使用of方法。ListStringfruitsList。of(apple,xiaomi,13xiang);MapInteger,StringnumbersMap。of(1,one,2,two,3,three);SetStringcolorsSet。of(yellow,red,baoqiang); 在Java9之前,我们想要创建一个不可变的集合,需要先创建一个可变集合,然后使用unmodifiableSet创建不可变集合,显然是很麻烦的。publicListStringfruits(){ListStringfruitsTmpnewArrayList();fruitsTmp。add(apple);fruitsTmp。add(xiaomi);fruitsTmp。add(13xiang);returnCollections。unmodifiableList(fruitsTmp);}publicMapInteger,Stringnumbers(){MapInteger,StringnumbersTmpnewHashMap();numbersTmp。put(1,one);numbersTmp。put(2,two);numbersTmp。put(3,three);returnCollections。unmodifiableMap(numbersTmp);}publicSetStringsetStr(){SetStringcolorsnewHashSet();colorsTmp。add(A);colorsTmp。add(B);colorsTmp。add(C);colorsTmpCollections。unmodifiableSet(colors);System。out。println(colorsTmp);returncolorsT} 同样,仅从ArrayList对象表创建即可使用Arrays。asList(。。。)method。publicListStringfruitsFromArray(){String〔〕fruitsArray{apple,xiaomi,13xiang};returnArrays。asList(fruitsArray);}92、接口里可以添加私有方法 基于JAVA8对接口增加了默认方法的支持,在JAVA9中对该功能进一步升级,可以在接口里定义私有方法,并且可以在默认方法里调用接口的私有方法。ublicinterfacetestInterface{Stringtest();接口默认方法defaultStringdefaultTest(){staticTest();}privateStringprivateTest(){System。out。println(privatemethodstaticTest);}}93、改进trywithresources Java9中不需要在try中额外定义一个变量。Java9之前需要这样使用trywithresources:InputStreaminputStreamnewStringBufferInputStream(陈哈哈);try(InputStreamininputStream){in。read();}catch(IOExceptione){e。printStackTrace();} 在Java9中可以在try中直接使用inputStream变量,不需要再额外定义新的变量了。InputStreaminputStreamnewStringBufferInputStream(陈哈哈);try(inputStream){inputStream。read();}catch(IOExceptione){e。printStackTrace();}94、多版本兼容jar包 Java9中支持在同一个JAR中维护不同版本的Java类和资源。95、增强了钻石操作符,可以在匿名内部类中使用了。 其实JAVA5就引入了泛型(generic),到了JAVA7开始支持钻石(diamond)运算符,,可以自动推断泛型的类型。 在Java9之前,内部匿名类需要指定泛型类型,如下:ListIntegernumbersnewArrayListInteger(){} 而在Java9中,可以自动做类型推导,如下:ListIntegernumbersnewArrayList(){}96、增强了JDK8特性 增强了JDK8的特性如:Stream,Optional,ProcessAPIJDK10(2018年3月)101、局部变量的自动类型推断(var)varaHello,Java10;System。out。println(a); JAVA10带来了一个很有意思的语法var,它可以自动推断局部变量的类型,以后再也不用写类型了,也不用靠lombok的var注解增强了 不过这个只是语法糖,编译后变量还是有类型的,使用时还是考虑下可维护性的问题。强调一下,var关键字目前只能用于局部变量以及for循环变量声明中。102、增强版Optional 从Java9和Java10开始,有几种用于Optional的有用方法。其中最有趣的两个是orElseThrow和ifPresentOrElse。 如果没有值,则使用该orElseThrow方法抛出NoSuchElementException。否则,它返回一个值。publicPersongetPersonById(Longid){OptionalPersonpersonOptrepository。findById(id);returnpersonOpt。orElseThrow();} 因此,我们可以避免将带参数的if语句与isPresentmethod一起使用。publicPersongetPersonByIdOldWay(Longid){OptionalPersonpersonOptrepository。findById(id);if(personOpt。isPresent())returnpersonOpt。get();elsethrownewNoSuchElementException();} 第二种有趣的方法是ifPresentOrElse。如果存在一个值,它将使用该值执行给定的操作。否则,它将执行给定的基于空的操作。publicvoidprintPersonById(Longid){OptionalPersonpersonOptrepository。findById(id);personOpt。ifPresentOrElse(System。out::println,()System。out。println(Personnotfound));} 在Java8中,我们可以ifelse直接与isPresent方法一起使用。publicvoidprintPersonByIdOldWay(Longid){OptionalPersonpersonOptrepository。findById(id);if(personOpt。isPresent())System。out。println(personOpt。get());elseSystem。out。println(Personnotfound);}Java11(2018年9月)111、Lambda中使用varpublicStringsumOfString(){BiFunctionString,String,Stringfunc(varx,vary)returnfunc。apply(abc,efg);}112、字符串API增强 Java11新增了一系列字符串处理方法,例如:判断字符串是否为空白、以及判空。isBlank();。isEmpty();Java11。stripTrailing();Java11Java11。stripLeading();Java11113、javacjava命令归一化 以前编译一个java文件时,需要先javac编译为class,然后再用java执行,现在可以放到一起执行了,香啊!javaHelloWorld。javaHelloJava11!JDK12(2019年3月)121、Switch表达式 我们可以定义多个case标签并使用箭头返回值,称之为:使用caseL箭头标签的switch。 此功能自JDK12起可用。它使Switch表达式真正更易于访问。publicStringnewSwitch(intday){returnswitch(day){case1,2,3摸鱼工作日;case4小周五;case5,6,7休息日;};} 如下代码:newSwitch(1);newSwitch(4);newSwitch(6); 结果如下:摸鱼工作日小周五休息日 而对于低于12的Java,相同的示例要复杂得多。publicStringoldSwitch(intday){switch(day){case1:case2:case3:return摸鱼工作日;case4:return小周五;case5:case6:case7:return休息日;default:}} 对于我们休息日和小周五的定义是不是感觉阵阵蒙圈?别意外,在我们的SQL大腿群中,小周五和周五已经成为了每周的传统节日,值得庆祝 122、instanceof类型强转一步到位 之前处理动态类型碰上要强转时,需要先instanceof判断一下,然后再强转为该类型处理:ObjectobjHelloJava12!;if(objinstanceofString){Strings(String)intlengths。length();} 现在instanceof支持直接类型转换了,不需要再来一次额外的强转:ObjectobjHelloJava12!;if(objinstanceofStringstr){intlengthstr。length();}JDK13(2019年9月)131、文本块(TextBlock)的支持 文本块是多行字符串文字,它避免使用转义序列,并以可预测的方式自动设置字符串格式。它还使开发人员可以控制字符串的格式。从Java13开始,文本块可用作预览功能。它们以三个双引号()开头。让我们看看我们如何轻松地创建和格式化JSON消息。publicStringgetNewPrettyPrintJson(){return{name:chenhaha,sex:undefined};} 创建Java13之前的相同JSON字符串要复杂得多。publicStringgetOldPrettyPrintJson(){return{name:chenhaha,sex:undefined};}132、增强switch语法: JAVA12中虽然增强了swtich语法,但并不能在之后写复杂的逻辑,JAVA13带来了swtich更完美的体验,就像lambda一样,可以写逻辑,然后再返回:intjnewSwitch(day){case1,2,3摸鱼工作日;case4小周五;case5,6,7休息日;default{varkday。toString()。length();varresf(k);}};JDK14(2020年3月)141、新增Record类 从Java14开始,引入了新的Record类。我们定义Record类时,使用关键字 使用Records可以定义不可变的纯数据类(仅限getter),也叫记录类。它会自动创建toString,equals和hashCode方法。实际上,只需要定义如下所示的字段即可。publicrecordPerson(Stringname,intage){} 具有类似功能的类如record包含字段,构造函数,getter和toString,equals以及hashCode方法。publicclassPersonOld{privatefinalSpublicPersonOld(Stringname,intage){this。this。}publicStringgetName(){}publicintgetAge(){}Overridepublicbooleanequals(Objecto){if(thiso)if(onullgetClass()!o。getClass())PersonOldpersonOld(PersonOld)o;returnagepersonOld。agename。equals(personOld。name);}OverridepublicinthashCode(){returnObjects。hash(name,age);}OverridepublicStringtoString(){returnPersonOld{namename,ageage};}}14。2、新增jpackage打包工具 新增jpackage打包工具,直接打包二进制程序,再也不用装JRE了! 之前如果想构建一个可执行的程序,还需要借助三方工具,将JRE一起打包,或者让客户电脑也装一个JRE才可以运行我们的JAVA程序。 现在JAVA直接内置了jpackage打包工具,帮助你一键打包二进制程序包,不用再乱折腾了。JDK15(2020年9月)151、ZGC和Shenandoah两款垃圾回收器正式登陆 在JAVA15中,ZGC和Shenandoah再也不是实验功能,正式登陆了(不过G1仍然是默认的)。如果你升级到JAVA15以后的版本,就赶快试试吧,性能更强,延迟更低。152、封闭(Sealed)类 使用密封类功能,可以限制超类的使用。使用new关键字,sealed可以定义哪些其他类或接口可以扩展或实现当前类。publicabstractsealedclassPetpermitsCat,Dog{} 允许的子类必须定义一个修饰符。如果不想允许任何其他扩展名,则需要使用final关键字。publicfinalclassCatextendsPet{} 另一方面,你可以打开扩展类。在这种情况下,应使用nonsealed修饰符。publicnonsealedclassDogextendsPet{} 当然,下面的可见声明是不允许的。publicfinalclassTigerextendsPet{}JAVA16(2021年3月) JAVA16在用户可见的地方变化并不多,基本都是1415的实验性内容;小结 那么开发人员为什么还坚持用Java8呢? 或许是因为升级在代码和维护层面或多或少会出现意想不到的BUG,很多企业求稳,领导们不愿随意改动。升级没问题的话领导倒是能多拿点儿提成,万一出了问题,领导能给你背锅?? 说回来程序员本身也不一定有时间去学习新特性和深入理解新的技术特性,有点时间多看看面试题它不香么? Java每三年会有一个长期支持的版本(LongTermSupportrelease,简称LTS),该版本会提供为期三年的支持。Java8是一个LTS,所以值得信赖。并且已基本被业内广泛使用,而下一个LTS分别是Java11和Java17,Mark一下吧。 但是,目前1线的java开发者中,应该还是大部分在使用Java8的版本。有数据统计80的人还在用JDK8,甚至有的公司还在使用JDK7。 问题来了?大家所用的Java版本是多少呢?原文链接:https:mp。weixin。qq。comsqXdzMF3DLBn0FNx7DBYHA 原作者:陈哈哈