Java 16~18新特性
Java16新特性
这里只介绍一些跟开发关联度较大的特性,除此之外JDK16还更新了许多其他新特性,感兴趣的同学可以去Oracle官网查看
包装类构造方法的警告
使用包装类的构造方法在编译的时候会出现警告,不建议再使用包装类的构造方法。下面代码在javac编译之后会出现警告。
Integer i = new Integer(8);
不建议使用包装类作为锁对象,倘若使用包装类作为锁对象,在编译时会出现警告。
Integer i = 8;
synchronized(i){
}
新增日时段
在DateTimeFormatter.ofPattern传入B可以获取现在时间对应的日时段,上午,下午等
System.out.println(DateTimeFormatter.ofPattern("B").format(LocalDateTime.now()));
InvocationHandler新增方法
在该接口中添加了下面方法
public static Object invokeDefault(Object proxy, Method method, Object... args)
该方法可以调用父接口中defalut方法,比如有下面接口
interface Girl{
default void eat(){
System.out.println("cucumber");
}
}
实现类
public class Lucy implements Girl{
public void eat(){
System.out.println("banana");
}
}
测试类:
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class Test{
public static void main(String[] args) {
Girl girl = new Lucy();
//不使用invokeDefault会调用重写的eat方法
Girl proxy1 = (Girl)Proxy.newProxyInstance(girl.getClass().getClassLoader(),girl.getClass().getInterfaces(),
(obj,method,params)->{
Object invoke = method.invoke(girl);
return invoke;
});
proxy1.eat();
//使用invokeDefault会调用父接口中的default方法
Girl proxy2 = (Girl)Proxy.newProxyInstance(Girl.class.getClassLoader(),new Class<?>[]{Girl.class},
(obj,method,params)->{
if (method.isDefault()) {
return InvocationHandler.invokeDefault(obj, method, params);
}
return null;
});
proxy2.eat();
}
}
其他
在之前jdk版本中作为预览功能的Record类,模式匹配的instanceof,打包工具jpackage,已成为正式版。jdk16对GC,jvm运行时内存等内容有一些变化,例如:ZGC并发栈处理,弹性meta space
Java17新特性
Java17是一个LTS(long term support)长期支持的版本,根据计划来看Java17会支持到2029年(java8会支持到2030年,OMG),同时Oracle提议下一个LTS版本是Java21,在2023年9月发布,这样讲LST版本的发布周期由之前的3年变为了2年。这里只介绍一些跟开发关联度较大的特性,除此之外JDK17还更新了一些其他新特性,感兴趣的同学可以从这里查看:https://www.oracle.com/news/announcement/oracle-releases-java-17-2021-09-14/
switch语法的变化(预览)
在之前版本中新增的instanceof 模式匹配的特性在switch中也支持了,即我们可以在switch中减少强转的操作。比如下面的代码:
Rabbit和Bird均实现了Animal接口
interface Animal{}
class Rabbit implements Animal{
//特有的方法
public void run(){
System.out.println("run");
}
}
class Bird implements Animal{
//特有的方法
public void fly(){
System.out.println("fly");
}
}
新特性可以减少Animal强转操作代码的编写:
public class Switch01{
public static void main(String[] args) {
Animal a = new Rabbit();
animalEat(a);
}
public static void animalEat(Animal a){
switch(a){
//如果a是Rabbit类型,则在强转之后赋值给r,然后再调用其特有的run方法
case Rabbit r -> r.run();
//如果a是Bird类型,则在强转之后赋值给b,然后调用其特有的fly方法
case Bird b -> b.fly();
//支持null的判断
case null -> System.out.println("null");
default -> System.out.println("no animal");
}
}
}
该功能在java17中是预览的,编译和运行需要加上额外的参数:
javac --enable-preview -source 17 Switch01.java
java --enable-preview Switch01
Sealed Classes
在jdk15中已经添加了Sealed Classes,只不过当时是作为预览版,经历了2个版本之后,在jdk17中Sealed Classes已经成为正式版了。Sealed Classes的作用是可以限制一个类或者接口可以由哪些子类继承或者实现。
伪随机数的变化
增加了伪随机数相关的类和接口来让开发者使用stream流进行操作
RandomGenerator
RandomGeneratorFactory
之前的java.util.Random和java.util.concurrent.ThreadLocalRandom都是RandomGenerator接口的实现类。
去除了AOT和JIT
AOT(Ahead-of-Time)是Java9中新增的功能,可以先将应用中的字节码编译成机器码。
Graal编译器作为使用java开发的JIT(just-in-time )即时编译器在java10中加入(注意这里的JIT不是之前java中的JIT,在JEP 317中有说明https://openjdk.java.net/jeps/317)。
以上两项功能由于使用量较少,且需要花费很多精力来维护,因此在java17中被移除了。当然你可以通过Graal VM来继续使用这些功能。
Java18新特性
这里只介绍一些跟开发关联度较大的特性,除此之外JDK18还更新了许多其他新特性,感兴趣的同学可以去Oracle官网查看:
https://www.oracle.com/java/technologies/javase/18-relnote-issues.html#NewFeature
默认使用UTF-8字符编码
从jdk18开始,默认使用UTF-8字符编码。我们可以通过如下参数修改其他字符编码:
-Dfile.encoding=UTF-8
简单的web服务器
可以通过jwebserver命令启动jdk18中提供的静态web服务器,可以利用该工具查看一些原型,做简单的测试。在命令提示符中输入jwebserver命令后会启动,然后在浏览器中输入:http://127.0.0.1:8000/ 即可看到当前命令提示符路径下的文件了。
将被移除的方法
在jdk18中标记了Object中的finalize方法,Thread中的stop方法将在未来被移除。
@snippet注解
以前在文档注释中编写代码时需要添加code标签,使用较为不便,通过@snippet注解可以更方便的将文档注释中的代码展示在api文档中。