提到JDK8的新特性,可能会想到Lambda、功能接口、Stream、Optional、日期时间API增强等等。
诚然,这些是我们每天都在使用的功能。不过你不关心的是,JDK已经悄悄更新到JDK16了(平均每半年一次),再过几个月就是JDK17了,哈哈哈!唉,真是大菜。
前两天粉丝们在分享面试问题的时候,我看到面试问题包括:请告诉我JDK8到JDK11有什么新功能?我很惊讶,都卷成这种吊状了?
虽然我也在使用JDK11,但我仍然停留在JDK8中寻找新功能。我们是老了还是追不上年轻人?下面是我对JDK版本的一些特性的总结,看看你还不知道什么。
在本文中,我们整理了一些可以在日常编程中使用的新功能。也许你会发现新大陆,并尽快更新自己的代码~ ~当然,尽量不要为了在线维护而更改代码,你知道的。
00-1010
JDK9(2017年9月)
借助Java 9的一个新功能,即集合工厂方法,我们可以使用预定义的数据轻松创建不可变的集合。您只需要在特定的集合类型上使用的方法。
ListString水果=List.of('苹果','小米',' 13香');MapInteger,String numbers=Map.of(1,1,2,2,3,3);SetString colors=Set.of('黄色','红色','包强');在Java 9之前,我们想创建一个不可变的集合。我们需要先创建一个变量集,然后使用未修改的变量集来创建一个不可变的集,这显然非常麻烦。
public ListString水果(){ ListString水果stmp=new ArrayList();水果stmp . add(' apple ');水果sTmp.add('小米');水果stmp . add(' 13 Xiang ');返回Collections.unmodifiableList(水果stmp);}public MapInteger,String numbers() { MapInteger,String numbersTmp=new HashMap();numbersTmp.put(1,' one ');numbersTmp.put(2,' two ');numbersTmp.put(3,'三');返回collections . unmodifielbeamp(numbersTmp);} public SetString setStr(){ SetString colors=new HashSet();colorstMP . add(' A ');颜色
sTmp.add("B");colorsTmp.add("C");colorsTmp = Collections.unmodifiableSet(colors);System.out.println(colorsTmp); return colorsTmp;}
同样,仅从ArrayList对象表创建即可使用Arrays.asList(...)method。
public List<String> fruitsFromArray() { String[] fruitsArray = {"apple", "xiaomi", "13xiang"}; return Arrays.asList(fruitsArray);}
9-2、接口里可以添加私有方法
基于JAVA 8 对接口增加了默认方法的支持,在 JAVA 9 中对该功能进一步升级,可以在接口里定义私有方法,并且可以在默认方法里调用接口的私有方法。
ublic interface testInterface { String test(); // 接口默认方法 default String defaultTest() { staticTest(); return "default"; } private String privateTest() { System.out.println("private method staticTest"); return "static"; }}
9-3、改进 try-with-resources
Java 9 中不需要在 try 中额外定义一个变量。Java 9 之前需要这样使用 try-with-resources:
InputStream inputStream = new StringBufferInputStream("陈哈哈");try (InputStream in = inputStream) { in.read();} catch (IOException e) { e.printStackTrace();}
在 Java 9 中可以在try中直接使用 inputStream 变量,不需要再额外定义新的变量了。
InputStream inputStream = new StringBufferInputStream("陈哈哈");try (inputStream) { inputStream.read();} catch (IOException e) { e.printStackTrace();}
9-4、多版本兼容 jar 包
Java 9 中支持在同一个 JAR 中维护不同版本的 Java 类和资源。
9-5、增强了钻石操作符 <>,可以在匿名内部类中使用了。
在 Java 9 之前,内部匿名类需要指定泛型类型,如下:
List<Integer> numbers = new ArrayList<Integer>() {}
而在 Java 9 中,可以自动做类型推导,如下:
List<Integer> numbers = new ArrayList<>() {}
9-6、增强了JDK8特性
增强了JDK8的特性如:Stream,Optional,Process API
JDK10(2018年3月)
10-1、局部变量的自动类型推断(var)
var a = "Hello, Java 10";System.out.println(a);
JAVA 10 带来了一个很有意思的语法var,它可以自动推断局部变量的类型,以后再也不用写类型了,也不用靠 lombok 的 var 注解增强了
不过这个只是语法糖,编译后变量还是有类型的,使用时还是考虑下可维护性的问题。强调一下,var 关键字目前只能用于局部变量以及 for 循环变量声明中。
10-2、增强版Optional
从Java 9和Java 10开始,有几种用于Optional的有用方法。其中最有趣的两个是orElseThrow和ifPresentOrElse。
如果没有值,则使用该orElseThrow方法抛出NoSuchElementException。否则,它返回一个值。
public Person getPersonById(Long id) { Optional<Person> personOpt = repository.findById(id); return personOpt.orElseThrow();}
因此,我们可以避免将带参数的if语句与isPresentmethod一起使用。
public Person getPersonByIdOldWay(Long id) { Optional<Person> personOpt = repository.findById(id); if (personOpt.isPresent()) return personOpt.get(); else throw new NoSuchElementException();}
第二种有趣的方法是ifPresentOrElse。如果存在一个值,它将使用该值执行给定的操作。否则,它将执行给定的基于空的操作。
public void printPersonById(Long id) { Optional<Person> personOpt = repository.findById(id); personOpt.ifPresentOrElse( System.out::println, () -> System.out.println("Person not found") );}
在Java 8中,我们可以if-else直接与isPresent方法一起使用。
public void printPersonByIdOldWay(Long id) { Optional<Person> personOpt = repository.findById(id); if (personOpt.isPresent()) System.out.println(personOpt.get()); else System.out.println("Person not found");}
Java 11(2018年9月)
11-1、Lambda 中使用 var
public String sumOfString() { BiFunction<String, String, String> func = (var x, var y) -> x + y; return func.apply("abc", "efg");}
11-2、字符串 API 增强
Java 11 新增了 一系列字符串处理方法,例如:
// 判断字符串是否为空白、以及判空" ".isBlank(); "".isEmpty(); " Java11 ".stripTrailing(); // " Java11"" Java11 ".stripLeading(); // "Java11 "
11-3、javac + java 命令归一化
以前编译一个 java 文件时,需要先 javac 编译为 class,然后再用 java 执行,现在可以放到一起执行了,香啊!
$ java HelloWorld.javaHello Java 11!
JDK 12(2019年3月)
12-1、Switch表达式
我们可以定义多个case标签并使用箭头返回值,称之为:使用case L ->箭头标签的switch。
此功能自JDK 12起可用。它使Switch表达式真正更易于访问。
public String newSwitch(int day) { return switch (day) { case 1, 2, 3 -> "摸鱼工作日"; case 4 -> "小周五"; case 5, 6, 7 -> "休息日"; default -> "invalid"; }; }
如下代码:
newSwitch(1);newSwitch(4);newSwitch(6);
结果如下:
摸鱼工作日小周五休息日
而对于低于12的Java,相同的示例要复杂得多。
public String oldSwitch(int day) { switch (day) { case 1: case 2: case 3: return "摸鱼工作日"; case 4: return "小周五"; case 5: case 6: case 7: return "休息日"; default: return "invalid"; } }
12-2、instanceof + 类型强转一步到位
之前处理动态类型碰上要强转时,需要先 instanceof 判断一下,然后再强转为该类型处理:
Object obj = "Hello Java 12!";if (obj instanceof String) { String s = (String) obj; int length = s.length();}
现在 instanceof 支持直接类型转换了,不需要再来一次额外的强转:
Object obj = "Hello Java 12!";if (obj instanceof String str) { int length = str.length();}
JDK 13(2019年9月)
13-1、文本块(Text Block)的支持
文本块是多行字符串文字,它避免使用转义序列,并以可预测的方式自动设置字符串格式。它还使开发人员可以控制字符串的格式。从Java 13开始,文本块可用作预览功能。它们以三个双引号(""")开头。让我们看看我们如何轻松地创建和格式化JSON消息。
public String getNewPrettyPrintJson() { return """ { "name": "chenhaha", "sex": "undefined" } """;}
创建Java 13之前的相同JSON字符串要复杂得多。
public String getOldPrettyPrintJson() { return "{\n" + " \"name\": \"chenhaha\",\n" + " \"sex\": \"undefined\"\n" + "}";}
13-2、增强 switch 语法:
JAVA 12 中虽然增强了 swtich 语法,但并不能在 -> 之后写复杂的逻辑,JAVA 13 带来了 swtich更完美的体验,就像 lambda一样,可以写逻辑,然后再返回:
int j = newSwitch (day) { case 1, 2, 3 -> "摸鱼工作日"; case 4 -> "小周五"; case 5, 6, 7 -> "休息日"; default -> { var k = day.toString().length(); var res = f(k); yield res; }};
JDK14(2020年3月)
14-1、新增 Record 类
从Java 14开始,引入了新的Record类。我们定义Record类时,使用关键字record;
使用Records可以定义不可变的纯数据类(仅限getter),也叫记录类。它会自动创建toString,equals和hashCode方法。实际上,只需要定义如下所示的字段即可。
public record Person(String name, int age) {}
具有类似功能的类如record包含字段,构造函数,getter和toString,equals以及hashCode方法。
public class PersonOld { private final String name; private final int age; public PersonOld(String name, int age) { this.name = name; this.age = age; } public String getName() { return name; } public int getAge() { return age; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; PersonOld personOld = (PersonOld) o; return age == personOld.age && name.equals(personOld.name); } @Override public int hashCode() { return Objects.hash(name, age); } @Override public String toString() { return "PersonOld{" + "name='" + name + '\'' + ", age=" + age + '}'; }}
14.2、新增 jpackage 打包工具
新增 jpackage 打包工具,直接打包二进制程序,再也不用装 JRE 了!
之前如果想构建一个可执行的程序,还需要借助三方工具,将 JRE 一起打包,或者让客户电脑也装一个 JRE 才可以运行我们的 JAVA 程序。
现在 JAVA 直接内置了 jpackage 打包工具,帮助你一键打包二进制程序包,不用再乱折腾了。
JDK15(2020年9月)
15-1、ZGC 和 Shenandoah 两款垃圾回收器正式登陆
在 JAVA 15中,ZGC 和 Shenandoah 再也不是实验功能,正式登陆了(不过 G1 仍然是默认的)。如果你升级到 JAVA 15 以后的版本,就赶快试试吧,性能更强,延迟更低。
15-2、封闭(Sealed)类
使用密封类功能,可以限制超类的使用。使用new关键字,sealed可以定义哪些其他类或接口可以扩展或实现当前类。
public abstract sealed class Pet permits Cat, Dog {}
允许的子类必须定义一个修饰符。如果不想允许任何其他扩展名,则需要使用final关键字。
public final class Cat extends Pet {}
另一方面,你可以打开扩展类。在这种情况下,应使用non-sealed修饰符。
public non-sealed class Dog extends Pet {}
当然,下面的可见声明是不允许的。
public final class Tiger extends Pet {}
JAVA 16(2021年3月)
JAVA 16 在用户可见的地方变化并不多,基本都是 14/15 的实验性内容;
小结
那么开发人员为什么还坚持用Java8呢?
或许是因为升级在代码和维护层面或多或少会出现意想不到的BUG,很多企业求稳,领导们不愿随意改动。升级没问题的话领导倒是能多拿点儿提成,万一出了问题,领导能给你背锅??
说回来程序员本身也不一定有时间去学习新特性和深入理解新的技术特性,有点时间多看看面试题它不香么?
Java每三年会有一个长期支持的版本(Long Term Support release,简称LTS),该版本会提供为期三年的支持。Java 8是一个LTS,所以值得信赖。并且已基本被业内广泛使用,而下一个LTS分别是Java11和Java17,Mark一下吧。
但是,目前1线的java开发者中,应该还是大部分在使用Java8的版本。有数据统计 80% 的人还在用JDK8,甚至有的公司还在使用JDK7。
内容来源网络,如有侵权,联系删除,本文地址:https://www.230890.com/zhan/149151.html