Java SE 16 新增特性
作者:Grey
原文地址:Java SE 16 新增特性
源码
镜像仓库: GitCode:java_new_features
使用反射执行接口中的默认实现方法
作为对接口中默认方法的增强,随着 Java SE 16 的发布,java.lang.reflect.InvocationHandler
可以通过使用反射调用接口的默认方法。
详见:JDK-8159746
参考如下示例
package git.snippets.jdk16; import java.lang.reflect.InvocationHandler; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import static java.lang.ClassLoader.getSystemClassLoader; /** * 反射调用接口的默认方法 * * @author <a href="mailto:410486047@qq.com">Grey</a> * @date 2022/8/21 * @since 16 */ public class InvocationEnhance { public static void main(String[] args) throws Exception { invoke(); } static void invoke() throws Exception { Object proxy = Proxy.newProxyInstance(getSystemClassLoader(), new Class<?>[]{HelloWorld.class}, (prox, method, args) -> { if (method.isDefault()) { return InvocationHandler.invokeDefault(prox, method, args); } // ... return prox; }); Method method = proxy.getClass().getMethod("hello"); System.out.println(method.invoke(proxy).equals("world")); } } interface HelloWorld { default String hello() { return "world"; } }
运行输出true
。
Sealed Classes 二次预览
Sealed Classes 是在Java SE 15中首次引入的,它提供了一种机制来确定哪些子类被允许扩展或实现父类或接口。在 Java SE 16 中, Sealed Classes 依然是预览状态。
Day Period Support
详见:JDK-8247781
DateTimeFormatter 的一个新成员是日周期符号 “B”,它提供了一个上午/下午格式的替代方案。
如下代码:
package git.snippets.jdk16; import java.time.LocalTime; import java.time.format.DateTimeFormatter; /** * 详见:https://docs.oracle.com/en/java/javase/16/docs/api/java.base/java/time/format/DateTimeFormatter.html * @author <a href="mailto:410486047@qq.com">Grey</a> * @date 2022/8/21 * @since 16 */ public class DayPeriodTest { public static void main(String[] args) { LocalTime date = LocalTime.now(); DateTimeFormatter formatter = DateTimeFormatter.ofPattern("B h:m"); System.out.println(date.format(formatter)); } }
输出下午 3:54
Stream.toList()
详见:JDK-8180352
其目的是减少一些常用的流收集器的模板代码,如Collectors.toList
和Collectors.toSet
。
示例代码如下
package git.snippets.jdk16; import java.util.Arrays; import java.util.List; import java.util.stream.Collectors; /** * @author <a href="mailto:410486047@qq.com">Grey</a> * @date 2022/8/21 * @since 16 */ public class StreamToListMethodDemo { public static void main(String[] args) { List<String> integersAsString = Arrays.asList("1", "2", "3"); // before jdk 16 List<Integer> ints = integersAsString.stream().map(Integer::parseInt).collect(Collectors.toList()); // jdk 16+ List<Integer> intsEquivalent = integersAsString.stream().map(Integer::parseInt).toList(); } }
打包工具增强
使用 jpackage 命令可以把 JAR 包打包成不同操作系统支持的软件格式,
在 Java SE 14 中是预览功能,到Java SE 16中正式启用
常见平台格式如下:
Linux 平台下为deb
和rpm
格式
MacOS 平台下为pkg
和dmg
格式
Windows 平台下为msi
和exe
格式
命令格式为:
jpackage --name myapp --input lib --main-jar main.jar --main-class myapp.Main
要注意的是,jpackage 不支持交叉编译,也就是说在 windows 平台上是不能打包成 MacOS 或者 Linux 系统的软件格式的。
instanceof 模式匹配
在 Java SE 14 中开始作为预览功能,Java SE 16 中被正式启用
package git.snippets.jdk16; import java.util.ArrayList; import java.util.Arrays; /** * instanceof * * @author <a href="mailto:410486047@qq.com">Grey</a> * @date 2021/11/29 * @since 16 */ public class InstanceofInJdk16 { public static void main(String[] args) { Object o = new ArrayList<String>(); // jdk 16 if (o instanceof ArrayList list) { list.add("a"); } // before jdk 16 if (o instanceof ArrayList) { ArrayList list = (ArrayList) o; list.add("a"); } } }
Records
在 Java SE 15 开始作为预览功能,Java SE 16 正式启用,示例代码如下:
package git.snippets.jdk16; /** * Records功能 * * @author <a href="mailto:410486047@qq.com">Grey</a> * @date 2021/11/29 * @since 16 */ public class RecordsInJava15 { public static void main(String[] args) { test(); } // record 是一种全新的类型,它本质上是一个 final 类, // 同时所有的属性都是 final 修饰,它会自动编译出 public get hashcode 、equals、toString 等方法,减少了代码编写量。 private static void test() { Cat c1 = new Cat("tomcat", 1); Cat c3 = new Cat("tomcat", 1); Cat c2 = new Cat("jerry", 2); System.out.println(c1); System.out.println(c2); System.out.println(c1 == c3); } } record Cat(String name, Integer age) { }