jdk17新特性梳理

jdk8升级至jdk17新特性梳理

因为公司后续将采用jdk17进行开发,顾进行一个jdk17新特性的简单梳理

升级jdk17的理由

最简单的理由就是,springboot3.0放弃了jdk8,kafka4.0同样放弃了jdk8

新特性梳理

可以在接口中定义私有方法,主要为了jdk8的default方法

public interface PricateMethodTest{
default void defaultMethod(){
privateMethod();
} private void privateMethod(){ }
}

局部变量可以使用var来定义

// jdk8的写法
String a1 = "111";
// jdk10之后的写法
var a2 = "222";

Http客户端链式操作

public class Test{
public static void main(String[] args){
var httpClient = HttpClient.newBuilder()
.version(HttpClient.Version.HTTP_1_1)
.connectTimeout(Duration.ofSeconds(10))
.build();
var resuest = HttpClient.newBuilder()
.GET()
.uri(URI.create("www.baidu.com"))
.setHeader("User-Agent","Google")
.build();
}
}

提供了原生的websocket相关api(这块暂无测试)

主要得益于SocketAPI 重构,Socket的底层实现优化,引入了NIO

空指针问题

在jdk14之前,异常捕获后抛出信息只有java.lang.NullPointerException

测试代码

public static void main(String[] args) {
try {
List<Integer> list = new ArrayList<>();
list.add(null);
System.out.println(list.get(0).longValue());
}catch (Exception e){
e.printStackTrace();
}
}

在jdk14之后,会显示具体的空指针对象,具体返回如下:

java.lang.NullPointerException: Cannot invoke "java.lang.Integer.longValue()" because the return value of "java.util.List.get(int)" is null

switch改造

jdk17之前版本采用了break返回的方式

public static int testBreak(String mode){
int i = 0;
switch(mode){
case "a","b":
i = 1;
break;
case "c":
i = 2;
break;
default:
i = 3;
break;
}
return i;
}

jdk14之后采用了yield

public static void testYield(String mode){
int result = switch(mode){
case "a","b":
yield 1; // 使用yield提供返回值
case "c":
yield 2; // 使用yield提供返回值
default:
yield 3; // 使用yield提供返回值
}
return result;
}

或者直接建图返回结果

public static void testYield(String mode){
int result = switch(mode){
case "a","b" -> 1;
case "c" -> 2;
default -> 3;
}
return result;
}

文本块的引入

// jdk1.8的写法
String html = "<html>\n" +
" <head>\n" +
" <title>test</title>\n" +
" </head>\n" +
" <body>\n" +
" <h1>test</h1>\n" +
" </body>\n" +
" </html>\n";
// jdk13的写法
var jdk15Html = """
<html>
<body>
<p>hello, world</p>
</body>
</html>
""";

instanceof的变化

jdk8是使用instanceof关键字判断类型之后,再强转,示例代码如下

// jdk8
if (obj instanceof String) {
String s = (String) obj;
if (s.equals("1")) {
System.out.println("1");
}
}
// jdk16,则直接可在if中完成操作,str为申明的变量
if (obj instanceof String str && str.equals("1")) {
System.out.println("1");
}

申明对象时可用record关键字实现get set方法

public record User(long id,String name,int age){

 }

提供了VarHandle

jdk9之后提供的VarHandle时对Unsafe的一个优化,jdk9之前的Unsafe是不建议开发者直接使用的,因为Unsafe所操作的并不属于Java标准,会容易带来一些安全性的问题

什么是VarHandle

Varhandle是对变量或参数定义的变量系列的动态强类型引用,包括静态字段,非静态字段,数组元素或堆外数据结构的组件。 在各种访问模式下都支持访问这些变量,包括简单的读/写访问,volatile 的读/写访问以及 CAS (compare-and-set)访问。简单来说 Variable 就是对这些变量进行绑定,通过 Varhandle 直接对这些变量进行操作。

举例

public class Demo {
public int publicVar = 1;
protected int protectedVar = 2;
private int privateVar = 3;
public int[] arrayData = new int[]{1, 2, 3};
@Override
public String toString() {
return "Demo{" +
"publicVar=" + publicVar +
", protectedVar=" + protectedVar +
", privateVar=" + privateVar +
", arrayData=" + Arrays.toString(arrayData) +
'}';
}
}
// 访问private成员
private static void privateDemo() throws NoSuchFieldException, IllegalAccessException {
Demo instance = new Demo();
VarHandle varHandle = MethodHandles.privateLookupIn(Demo.class, MethodHandles.lookup())
.findVarHandle(Demo.class, "privateVar", int.class);
varHandle.set(instance, 33);
System.out.println(instance);
}

输出:Demo

// 访问 protected 成员
private static void protectedDemo() throws NoSuchFieldException, IllegalAccessException {
Demo instance = new Demo(); VarHandle varHandle = MethodHandles.privateLookupIn(Demo.class,MethodHandles.lookup())
.findVarHandle(Demo.class, "protectedVar", int.class); VarHandle varHandle = MethodHandles.lookup()
.in(Demo.class)
.findVarHandle(Demo.class, "protectedVar", int.class);
varHandle.set(instance, 22);
System.out.println(instance);
}

输出:Demo

// 访问public成员
private static void publicDemo() throws NoSuchFieldException, IllegalAccessException {
Demo instance = new Demo();
VarHandle varHandle = MethodHandles.lookup()
.in(Demo.class)
.findVarHandle(Demo.class, "publicVar", int.class);
varHandle.set(instance, 11);
System.out.println(instance);
}

输出:Demo

// 访问数组
private static void arrayDemo() throws NoSuchFieldException, IllegalAccessException {
Demo instance = new Demo();
VarHandle arrayVarHandle = MethodHandles.arrayElementVarHandle(int[].class);
arrayVarHandle.compareAndSet(instance.arrayData, 0, 1, 11);
arrayVarHandle.compareAndSet(instance.arrayData, 1, 2, 22);
arrayVarHandle.compareAndSet(instance.arrayData, 2, 3, 33);
System.out.println(instance);
}

输出:Demo

Varhandle方法汇总

  • MethodHandles.privateLookupIn(class, MethodHandles.lookup())获取访问私有变量的Lookup
  • MethodHandles.lookup() 获取访问protected、public的Lookup
  • findVarHandle:用于创建对象中非静态字段的VarHandle。接收参数有三个,第一个为接收者的class对象,第二个是字段名称,第三个是字段类型。
  • findStaticVarHandle:用于创建对象中静态字段的VarHandle,接收参数与findVarHandle一致。
  • unreflectVarHandle:通过反射字段Field创建VarHandle。
  • MethodHandles.arrayElementVarHandle(int[].class) 获取管理数组的 Varhandle

内存屏障

VarHandle 除了支持各种访问模式下访问变量之外,还提供了一套内存屏障方法,目的是为了给内存排序提供更细粒度的控制。主要如下几个方法:

public static void fullFence() {
UNSAFE.fullFence();
}
public static void acquireFence() {
UNSAFE.loadFence();
}
public static void releaseFence() {
UNSAFE.storeFence();
}
public static void loadLoadFence() {
UNSAFE.loadLoadFence();
}
public static void storeStoreFence() {
UNSAFE.storeStoreFence();
}

小结

在 java9 之后,对一些变量的并发操作时,可以考虑用 java.lang.invoke.VarHandle 来处理,而不是通过 Unsafe 类来处理,毕竟 Unsafe 不太适合直接使用。

Sealed Classes(封闭类)

  • 密封Sealed表示的概念是可以扩展一个类,但只能通过已知的子类型列表进行扩展,而不能通过其他任何扩展。
  • 其他语言可能对功能的看法有所不同,在Java中,应将其视为代表几乎最终类的功能。
  • Java 16开始,允许使用 sealed 修饰class,并通过permits明确写出能够从该class继承的子类名称。
// 测试代码
public sealed class Car permits MiniCar, SmallCar, Bigcar{
...
}
// 以下代码可以正常运行
public final class MiniCar extends Car {...}
// 以下代码会报错
public final class Train extends Car {...}

其他新特性

其他新特性有待于各位小伙伴努力尝试

来源:不晓得哪里抄的

jdk17新特性梳理的更多相关文章

  1. MySQL 8.0 新特性梳理汇总

    一 历史版本发布回顾 从上图可以看出,基本遵循 5+3+3 模式 5---GA发布后,5年 就停止通用常规的更新了(功能不再更新了): 3---企业版的,+3年功能不再更新了: 3 ---完全停止更新 ...

  2. 从Java 9 到 Java 17 新特性梳理

    Java 9 新的创建集合的方法  // [1, 2, 3, 4]  List<Integer> integers = List.of(1, 2, 3, 4);  // {1,2,3}   ...

  3. JDK8到JDK17有哪些吸引人的新特性?

    作者:京东零售 刘一达 前言 2006年之后SUN公司决定将JDK进行开源,从此成立了OpenJDK组织进行JDK代码管理.任何人都可以获取该源码,并通过源码构建一个发行版发布到网络上.但是需要一个组 ...

  4. Atitit js版本es5 es6新特性

    Atitit js版本es5 es6新特性 Es5( es5 其实就是adobe action script的标准化)1 es6新特性1 Es5( es5 其实就是adobe action scrip ...

  5. 各版本JDK1.5-1.8新特性

    概述 一jdk15新特性 泛型 foreach 自动拆箱装箱 枚举 静态导入Static import 元数据Metadata 线程池 Java Generics 二jdk16新特性 Desktop类 ...

  6. 终极CURD-4-java8新特性

    目录 1 概述 2 lambda表达式 2.1 lambda重要知识点总结 2.2 java内置函数接口 2.3 方法引用 2.4 构造器引用 2.5 数组引用 2.6 lambda表达式的陷阱 3 ...

  7. Java9-17新特性一览,了解少于3个你可能脱节了

    前言 Java8出来这么多年后,已经成为企业最成熟稳定的版本,相信绝大部分公司用的还是这个版本,但是一眨眼今年Java19都出来了,相信很多Java工程师忙于学习工作对新特性没什么了解,有的话也仅限于 ...

  8. 简单梳理下 Vue3 的新特性

    在 Vue3 测试版刚刚发布的时候,我就学习了下 Composition API,但没想到正式版时隔一年多才出来,看了一下发现还是增加了不少新特性的,在这里我就将它们一一梳理一遍. 本文章只详细阐述 ...

  9. 开发者所需要知道的 iOS 10 SDK 新特性

    转自:https://onevcat.com/2016/06/ios-10-sdk/ 写的很好啊.哈哈哈 总览 距离 iPhone 横空出世已经过去了 9 个年头,iOS 的版本号也跨入了两位数.在我 ...

  10. CSS3新特性罗列

    接触CSS3这么久了,总是到要用的时候直接拿来用,却没有好好地总结归纳一下,那就在这里好好梳理一下吧. CSS3边框: 圆角边框: 关键:border-radius <!DOCTYPE html ...

随机推荐

  1. NativeMemoryTracking的再学习

    摘要 最近一段时间学习jvm比较多. 为了能够更加深入的进行一些调优和峰值性能的配置. 看了很多像是NMT,inline,堆区方法区以及分层编译等知识. 但是看到华为毕昇社区说的codecache相关 ...

  2. Loki动态展示linux本地日志

    Loki动态展示linux本地日志 背景 产品需要拆分微服务部署,直接使用K8S部署虽然比较规范但是部署时间较长. 本地文件系统部署简洁快速一些, 但是不太好直接复用一些规范的产品. 本次处理方法就是 ...

  3. Oracle 建立数据库dblink 然后同步部分表内容的总结

    同步处理部分数据 背景 最近在项目上发现两个分库进行数据同步时部分内容同步存在问题. 最简单的方法是导表,但是害怕有其他关联信息异常, 所以同事想到了dblink的方式. 这里简单整理一下 同事用到的 ...

  4. 范德蒙德矩阵行列式 & 循环矩阵行列式的证明

    范德蒙德矩阵的行列式 \[\begin{vmatrix} 1 & 1 & 1 & \dots & 1 \\ x_1 & x_2 & x_3 & ...

  5. Istio安装和部署

    Istio的版本对k8s的版本是有要求的,不兼容的版本会引发一些隐蔽的错误,安装前先参考下图 版本 目前支持 发行日期 停止维护 支持的 Kubernetes 版本 未测试,可能支持的 Kuberne ...

  6. web开发的模式的介绍与身份认证

    web开发的模式的介绍 1.服务端渲染 2.前端端分离开发的web模式 服务端渲染优点与缺点 优点: 1.前端耗时少.因为服务器端负责动态生成HTML内容,浏览器只需要直接渲染页面即可.尤其是移动端更 ...

  7. Ant Design Vue 单文件上传Upload

    单文件上传 <a-upload name="file" :beforeUpload="beforeUpload" :multiple="fals ...

  8. git查看自己是从那个分支建的分支

    可能发生的情况 很多时候,开始建分支的时候, 能够确认自己是那个分支建的,但是当写完功能之后, 再去回想,有时是忘记自己基于那个分支建的分支. 这时有一个命令的话就可以很快的定位了. 查看创建的分支来 ...

  9. Vue中Vue.set()和this.$forceUpdate()的使用

    1.给对象添加一个key值 成功的 <template> <div> <p>{{userInfo.name}}</p> <p>{{userI ...

  10. MacBook m2 笔记本 + k8s容器环境开发笔记

    作者:张富春(ahfuzhang),转载时请注明作者和引用链接,谢谢! cnblogs博客 zhihu Github 公众号:一本正经的瞎扯 为最近两周在 MacBook m2 + k8s 容器环境的 ...