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. [转帖]nmon使用及监控数据分析

    [使用] [监控数据分析] 参考链接:nmon监控数据分析 性能测试中,各个服务器资源占用统计分析是一个很重要的组成部分,通常我们使用nmon这个工具来进行监控以及监控结果输出. 一.在监控阶段使用类 ...

  2. 拼多多的U盘都是垃圾

    春节期间陪孩子玩拼多多的果园, 然后发现推送的U盘很便宜就买了下 结果发现.. U盘都是扩容盘,非常垃圾 如下图: 警告: 只有 255933 MB可测试,总容量 255935 MB. 媒体很可能已损 ...

  3. 文心一言 VS 讯飞星火 VS chatgpt (187)-- 算法导论14.1 4题

    四.用go语言,写出一个递归过程 OS-KEY-RANK(T,k),以一棵顺序统计树T和一个关键字k作为输入,要求返回 k 在由 T 表示的动态集合中的秩.假设 T 的所有关键字都不相同. 文心一言, ...

  4. HBase深度历险 | 京东物流技术团队

    简介 HBase 的全称是 Hadoop Database,是一个分布式的,可扩展,面向列簇的数据库,是一个通过大量廉价的机器解决海量数据的高速存储和读取的分布式数据库解决方案.本文会像剥洋葱一样,层 ...

  5. 为什么Kubernetes和容器与机器学习密不可分?

    原文出自infosecurity 作者:Rebecca James 京东云开发者社区编译 当前,数字化转型的热潮在IT领域发展的如火如荼,越来越多的企业投身其中,机器学习和人工智能等现代技术的融合在公 ...

  6. It is currently in use by another Gradle instance

    FAILURE: Build failed with an exception. * What went wrong: Could not create service of type TaskHis ...

  7. typeScript类型别名

    类型别名 类型别名:是可以给一个类型起一个新的名字 采用关键字 type 例如 type Name=string|number type strType=string|number|boolean; ...

  8. 【小实验】使用 wrk 的 docker 容器来压测另一个容器

    作者:张富春(ahfuzhang),转载时请注明作者和引用链接,谢谢! cnblogs博客 zhihu Github 公众号:一本正经的瞎扯 GET 请求 想压测容器环境的服务性能,发现两个麻烦: 本 ...

  9. 【JS 逆向百例】有道翻译接口参数逆向

    逆向目标 目标:有道翻译接口参数 主页:https://fanyi.youdao.com/ 接口:https://fanyi.youdao.com/translate_o?smartresult=di ...

  10. 微服务用yml安装系统(第一版)

    当用微服务安装系统后,面临服务较多,一个一个安装比较麻烦,是否有统一的脚本可以直接执行安装呢?答案是肯定的: 1.首先介绍一下所有安装脚本,如下图 spd-volume:是各服务外挂的资料卷 comm ...