JDK15真的来了,一起来看看它的新特性
简介
一年两次的JDK最新版本JDK15在2020年9月15日正式发布了,这次的JDK15给我们带了隐藏类,EdDSA,模式匹配,Records,封闭类和Text Block等诸多新特性。
一起来看看吧。
JDK15的新特性
JEP 385 Deprecate RMI Activation for Removal
RMI Activation被标记为Deprecate,将会在未来的版本中删除。
RMI大家应该都清楚,RMI就是Remote Method Invocation,翻译成中文就是远程方法调用,是在JDK1.2中引入的。
RMI为java提供了开发分布式系统的强大能力。而J2EE的规范EJB就是使用RMI来实现的bean的远程调用的。
在RMI系统中,远程系统中存在很多分布式对象,如果这些分布式对象一直处于活动状态的话,将会占用很多宝贵的系统资源。
于是RMI引入了一种lazy Activation的方式,这种方式就叫做延迟激活。
这里有两个概念,活动对象和被动对象。
活动对象是在某些系统上的JVM中实例化并对外暴露的远程对象。被动对象是尚未在JVM中实例化(或暴露)但可以进入主动状态的对象。
将被动对象转换为主动对象的过程称为激活。激活要求对象与JVM关联,这可能会将该对象的类加载到JVM中,并且将该对象恢复为之前的状态。
在RMI系统中,我们使用延迟激活。延迟激活将激活对象推迟到客户第一次使用(即第一次方法调用)之前。
既然RMI Activation这么好用,为什么要废弃呢?
因为对于现代应用程序来说,分布式系统大部分都是基于Web的,web服务器已经解决了穿越防火墙,过滤请求,身份验证和安全性的问题,并且也提供了很多延迟加载的技术。
所以在现代应用程序中,RMI Activation已经很少被使用到了。并且在各种开源的代码库中,也基本上找不到RMI Activation的使用代码了。
为了减少RMI Activation的维护成本,在JDK8中,RMI Activation被置为可选的。现在在JDK15中,终于可以废弃了。
JEP 371 Hidden Classes
Hidden Classes是什么呢?
Hidden Classes就是不能直接被其他class的二净值代码使用的class。Hidden Classes主要被一些框架用来生成运行时类,但是这些类不是被用来直接使用的,而是通过反射机制来调用。
通常来说基于JVM的很多语言都有动态生成类的机制,这样可以提高语言的灵活性和效率。
比如在JDK8中引入的lambda表达式,JVM并不会在编译的时候将lambda表达式转换成为专门的类,而是在运行时将相应的字节码动态生成相应的类对象。
另外使用动态代理也可以为某些类生成新的动态类。
那么我们希望这些动态生成的类需要具有什么特性呢?
不可发现性。因为我们是为某些静态的类动态生成的动态类,所以我们希望把这个动态生成的类看做是静态类的一部分。所以我们不希望除了该静态类之外的其他机制发现。
访问控制。我们希望在访问控制静态类的同时,也能控制到动态生成的类。
生命周期。动态生成类的生命周期一般都比较短,我们并不需要将其保存和静态类的生命周期一致。
但是现有的类的定义API ClassLoader::defineClass和Lookup::defineClass是不管类的字节码是如何生成的,他们都是平等对待。
所以我们需要一些API来定义无法发现的且具有有限生命周期的隐藏类。这将提高所有基于JVM的语言实现的效率。
比如:
java.lang.reflect.Proxy可以定义隐藏类作为实现代理接口的代理类。
java.lang.invoke.StringConcatFactory可以生成隐藏类来保存常量连接方法;
java.lang.invoke.LambdaMetaFactory可以生成隐藏的nestmate类,以容纳访问封闭变量的lambda主体;
JavaScript引擎可以为从JavaScript程序转换的字节码生成隐藏的类,因为当引擎不再使用它们时,这些类将被卸载。
普通类是通过调用ClassLoader::defineClass创建的,而隐藏类是通过调用Lookup::defineHiddenClass创建的。
这使JVM从提供的字节中派生一个隐藏类,链接该隐藏类,并返回提供对隐藏类的反射访问的查找对象。
调用程序可以通过返回的查找对象来获取隐藏类的Class对象。
JEP 339 Edwards-Curve Digital Signature Algorithm (EdDSA)
实现了EdDSA椭圆曲线签名算法。
这里就不多讲椭圆曲线签名算法了,如果又想了解的朋友可以给我留言。
JEP 375 Pattern Matching for instanceof (Second Preview)
Pattern Matching 就是说可以在做pattern mathching的时候,直接对该对象进行类型的转换。
现在这个特性还是预览版本的。
我们看一下具体的例子:
if (obj instanceof String) {
String s = (String) obj;
// use s
}
在Pattern Matching之前,我们使用instanceof之后,还需要对该对象进行强制类型转换才能使用。
但是在Pattern Matching之后,我们可以这样用:
if (obj instanceof String s) {
// can use s here
} else {
// can't use s here
}
是不是很方便。
JEP 384 Records (Second Preview)
Record是一种轻量级的class,可以看做是数据结构体。和scala中的case有点相似。
举个自定义User的例子看一下Record是怎么用的:
public record Address(
String addressName,
String city
) {
}
public record CustUser(
String firstName,
String lastName,
Address address,
int age
) {}
上面我们定义了两个类,CustUser和Address。CustUser中引用了Address。
Record和普通的类的区别就在于Record多了一个括号括起来的定义的字段。
Record类默认是final的,里面的字段默认是private final的。
要想知道Record到底是怎么工作的,我们可以使用javap来对编译好的class文件反编译,运行javap CustUser,可以得到下面的结果:
警告: 二进制文件CustUser包含com.flydean.records.CustUser
Compiled from "CustUser.java"
public final class com.flydean.records.CustUser extends java.lang.Record {
public com.flydean.records.CustUser(java.lang.String, java.lang.String, com.flydean.records.Address, int);
public java.lang.String toString();
public final int hashCode();
public final boolean equals(java.lang.Object);
public java.lang.String firstName();
public java.lang.String lastName();
public com.flydean.records.Address address();
public int age();
}
上面可以看到final class CustUser继承自java.lang.Record。
并且自动添加了默认带有所有字段的构造函数。各个自动的获取方法,并实现了toString,hashCode和equals方法。
天啦,太完美了,我们想要的它居然都有。
如果上面的javap还不是很清楚的话,大家可以借助IDE的反编译功能,打开CustUser.class文件看一看:
public final class CustUser extends java.lang.Record {
private final java.lang.String firstName;
private final java.lang.String lastName;
private final com.flydean.records.Address address;
private final int age;
public CustUser(java.lang.String firstName, java.lang.String lastName, com.flydean.records.Address address, int age) { /* compiled code */ }
public java.lang.String toString() { /* compiled code */ }
public final int hashCode() { /* compiled code */ }
public final boolean equals(java.lang.Object o) { /* compiled code */ }
public java.lang.String firstName() { /* compiled code */ }
public java.lang.String lastName() { /* compiled code */ }
public com.flydean.records.Address address() { /* compiled code */ }
public int age() { /* compiled code */ }
}
注意,上面的反编译我们可以看到,record中的所有字段都是final的,只能在初始化的时候设置。并且方法里面也没有提供其他可以改变字段内容的方法。
所以我们得出了一个震世惊俗的结论:record是immutable的。
上面的例子中我们只使用了小括号里面的内容,大括号还是空的呀。可不可以像其他正常的类一样,添加点方法或者构造函数进去呢?
答案是肯定的。
先看一个整体的方案:
public record CustUserWithBody(
String firstName,
String lastName,
Address address,
int age
) {
public String fullName(){
return firstName+ lastName;
}
public CustUserWithBody{
if (age < 18) {
throw new IllegalArgumentException( "男大当婚,女大当嫁,18岁未到,不许出嫁!");
}
}
}
我们在record的主题中,定义了一个方法和一个构造函数。
先看这个方法,在方法中我们可以访问到record中定义的变量,但是千万不要尝试去修改他们,因为他们是final的,你会得到一个变异错误。
再看这个构造函数,这个构造函数没有小括号,只有大括号,这种构造函数叫做Compact constructor。你无法在record中定义正常的构造函数,因为会得到一个编译错误。
在这个Compact constructor中,我们可以对定义的字段进行数据校验。如上所述。
JEP 360 Sealed Classes (Preview)
在Java中,类层次结构通过继承实现代码的重用,父类的方法可以被许多子类继承。
但是,类层次结构的目的并不总是重用代码。有时,其目的是对域中存在的各种可能性进行建模,例如图形库支持的形状类型或金融应用程序支持的贷款类型。
当以这种方式使用类层次结构时,我们可能需要限制子类集从而来简化建模。
因为我们引入了sealed class或interfaces,这些class或者interfaces只允许被指定的类或者interface进行扩展和实现。
举个例子:
package com.example.geometry;
public abstract sealed class Shape
permits Circle, Rectangle, Square {...}
上面的例子中,我们指定了Shape只允许被Circle, Rectangle, Square来继承。
上面的例子中并没有指定类的包名,我们可以这样写:
package com.example.geometry;
public abstract sealed class Shape
permits com.example.polar.Circle,
com.example.quad.Rectangle,
com.example.quad.simple.Square {...}
JEP 378 Text Blocks
Text Blocks是为了解决在java中输入多行数据的问题。
比如:
String html = "<html>\n" +
" <body>\n" +
" <p>Hello, world</p>\n" +
" </body>\n" +
"</html>\n";
可以写成:
String html = """
<html>
<body>
<p>Hello, world</p>
</body>
</html>
""";
String query = "SELECT \"EMP_ID\", \"LAST_NAME\" FROM \"EMPLOYEE_TB\"\n" +
"WHERE \"CITY\" = 'INDIANAPOLIS'\n" +
"ORDER BY \"EMP_ID\", \"LAST_NAME\";\n";
可以写成:
String query = """
SELECT "EMP_ID", "LAST_NAME" FROM "EMPLOYEE_TB"
WHERE "CITY" = 'INDIANAPOLIS'
ORDER BY "EMP_ID", "LAST_NAME";
非常的方便。
总结
好了,JDK15的新特性全都介绍完了。希望大家能够喜欢。
本文作者:flydean程序那些事
本文链接:http://www.flydean.com/jdk15-release-new-features/
本文来源:flydean的博客
欢迎关注我的公众号:「程序那些事」最通俗的解读,最深刻的干货,最简洁的教程,众多你不知道的小技巧等你来发现!
JDK15真的来了,一起来看看它的新特性的更多相关文章
- JDK15就要来了,你却还不知道JDK8的新特性!
微信搜「烟雨星空」,白嫖更多好文. 现在 Oracle 官方每隔半年就会出一个 JDK 新版本.按时间来算的话,这个月就要出 JDK15 了.然而,大部分公司还是在使用 JDK7 和 8 . 之前去我 ...
- 史上最全jdk新特性总结,涵盖jdk8到jdk15!
前言 在本文中,我将描述自第8版以来Java最重要且对开发人员友好的功能.为什么会有这样的主意?在Web上,您可以找到许多文章,其中包含每种Java版本的新功能列表.但是,由于缺少文章,因此无法简要概 ...
- IntelliJ IDEA 2019.3 这回真的要飞起来了,新特性抢先看!
IntelliJ IDEA 才公布下一个主要版本 2019.3 的 Roadmap,近日就发布了 IntelliJ IDEA 2019.3 的首个早期访问版本(即 EAP 版本),版本号为 2019. ...
- 【Java8新特性】重复注解与类型注解,你真的学会了吗?
写在前面 在Java8之前,在某个类或者方法,字段或者参数上标注注解时,同一个注解只能标注一次.但是在Java8中,新增了重复注解和类型注解,也就是说,从Java8开始,支持在某个类或者方法,字段或者 ...
- CSS基础(一):开篇
背景 HTML是一种超文本标记语言,用来定义文档的结构和内容,例如标题.段落和列表等等,而文档内容如何渲染.如何展示,这就需要样式来修饰了.CSS正是可以与HTML很好地结合.如果将HTML比作水,那 ...
- JDK15正式发布,划时代的ZGC同时宣布转正
你发任你发,我用Java8.本文已被 https://www.yourbatman.cn 收录,里面一并有Spring技术栈.MyBatis.JVM.中间件等小而美的专栏供以免费学习.关注公众号[BA ...
- HTTP真的很简单
原文:HTTP Made Really Easy因为我本身网络基础就很差,所以看到这篇文章一方面是学习网络知识,另一方面为了锻炼我蹩脚的英语水平,文中如有错误,欢迎浏览指正! 前言 在看这篇文章的时候 ...
- HTTP真的很简单(转)
原文:HTTP Made Really Easy因为我本身网络基础就很差,所以看到这篇文章一方面是学习网络知识,另一方面为了锻炼我蹩脚的英语水平,文中如有错误,欢迎浏览指正! 前言 在看这篇文章的时候 ...
- SQL Server数据库的存储过程中定义的临时表,真的有必要显式删除临时表(drop table #tableName)吗?
本文出处:http://www.cnblogs.com/wy123/p/6704619.html 问题背景 在写SQL Server存储过程中,如果存储过程中定义了临时表,有些人习惯在存储过程结束的时 ...
随机推荐
- Antd cracoTs Js 配置流程
JS:文档:0.1.4 配置 js 环境.note链接:http://note.youdao.com/noteshare?id=e32fa75c1baa014b5819fa5e22887dbc& ...
- oracle 将数据库的表复制到另一个数据库表内
将数据库A中的表sys_role复制到数据库B中在数据库b中的SQL工作表写如下代码: 第一步:建立链接 CREATE database link A //数据库名称CONNECT to text ...
- 这可能是最详细的解析HTTP走私攻击的文章
前言 HTTP Desync Attacks也就是HTTP走私攻击,是我见到的比较有趣的一种攻击方式,这里来对这种漏洞进行介绍. TL;DR HTTP走私攻击利用了HTTP协议本身的问题:HTTP中存 ...
- muduo源码解析3-currentthread命名空间
CurrentThread 作用: CurrentThread并不是一个类,而是一个命名空间,在mymuduo内部,目的是提供对于当前线程的管理操作. 内部变量: __thread int t_cac ...
- 以Winsows Service方式运行JupyterLab
有数据分析,数据挖掘,以及机器学习和深度学习实践经验的读者应该会对Jupyter Notebook这一工具十分熟悉,而JupyterLab是它的升级版本,其提供了更具扩展性,更加可定制化的功能选项. ...
- Netty源码分析之ByteBuf(一)—ByteBuf中API及类型概述
ByteBuf是Netty中主要的数据容器与操作工具,也是Netty内存管理优化的具体实现,本章我们先从整体上对ByteBuf进行一个概述: AbstractByteBuf是整个ByteBuf的框架类 ...
- 无法创建新虚拟机: 无法打开配置文件“F:\BigData\vm12\centos01\centos01.vmx”: 拒绝访问。
退出,右键vmware选择以管理员身份运行即可.
- asterisk PBX 对接中国移动IMS
前提: 最近有项目需求,需要对接移动的IMS,移动的对接同事给出了信息: 用户名:+86750735xxxx@ims.gd.chinamobile.com 密码:123456 (系统导入的号码,默认 ...
- vue 中PDF实现在线浏览,禁止下载,打印
需求:在线浏览pdf文件,并且禁止掉用户下载打印的效果. 分析:普通的iframe.embed标签都只能实现在线浏览pdf的功能,无法禁止掉工具栏的下载打印功能.只能尝试使用插件,pdfobject. ...
- JVM内存区域以及各区域的内存溢出异常,内存分代策略,垃圾收集算法,各种垃圾收集器
本文整理自周志明老师的<深入理解Java虚拟机-JVM高级特性与最佳实践>第3版的第二章和第三章. 加上了一些网上拼拼凑凑的图片,个人认为很多博客复制来复制去,最后的东西都看不懂,所以从书 ...