浅谈java15新特性

你发任你发,我用Java8 

jdk15的安装和新版idea的安装就不说了,下面奉上两个软件。

链接: https://pan.baidu.com/s/1hOb0CChSfYotFl3s3QL2yA  密码: mp6a

安装完成之后, java -version 查看版本确认环境无误。

新版idea,需要额外做以下设置。

ok,环境已经ok,开始编码。

这次发布的主要功能有: 

Java 15为用户提供了14项主要的增强/更改,包括一个孵化器模块,三个预览功能,两个不推荐使用的功能以及两个删除功能。 

http://openjdk.java.net/projects/jdk/15/ 

对应中文特性:(JEP:JDK Enhancement Proposals,JDK 增强建议,也就是 JDK 的特性新增和改进提案。) 

  • JEP 339:EdDSA 数字签名算法 
  • JEP 360:密封类(预览) 
  • JEP 371:隐藏类 
  • JEP 372:移除 Nashorn JavaScript 引擎 
  • JEP 373:重新实现 Legacy DatagramSocket API 
  • JEP 374:禁用偏向锁定 
  • JEP 375:instanceof 模式匹配(第二次预览) 
  • JEP 377:ZGC:一个可扩展的低延迟垃圾收集器 
  • JEP 378:文本块 
  • JEP 379:Shenandoah:低暂停时间垃圾收集器 
  • JEP 381:移除 Solaris 和 SPARC 端口 
  • JEP 383:外部存储器访问 API(第二次孵化版) 
  • JEP 384:Records(第二次预览) 
  • JEP 385:废弃 RMI 激活机制 

总结: 

  • 借用大佬的话:JDK15整体来看新特性方面并不算很亮眼,它主要是对之前版本 预览特性 的功能做了确定,如文本块、ZGC等,这么一来我们就可以放心大胆的使用了。 

为什么大佬说本次新特性不算很亮眼呢?本次主要特性是以下六个:

JEP 360:密封类(预览)、  ( 此概念其实也不是java语言首创,其他语言之前就有提到过)

JEP 371:隐藏类、                 (此概念其实也不是java语言首创,其他语言之前就有提到过)

JEP 375:instanceof 模式匹配(第二次预览)、

JEP 384:Records(第二次预览)

JEP 377:ZGC:一个可扩展的低延迟垃圾收集器、   (之前的功能转正)

JEP 378:文本块、    ( 之前的功能转正)

一、 JEP 360: Sealed Classes(Preview) 密封的类和接口(预览) 

        用于限制超类的使用,密封的类和接口限制其它可能继承或实现它们的其它类或接口。

        具体使用: 

        因为我们引入了sealed class或interfaces,这些class或者interfaces只允许被指定的类或者interface进行扩展和实现。 

        使用修饰符sealed,您可以将一个类声明为密封类。密封的类使用reserved关键字permits列出可以直接扩展它的类。子类可以          是最终的,非密封的或密封的。 

        之前我们的代码是这样的。 

public class Person { } //人

class Teacher extends Person { }//教师

class Worker extends Person { }  //工人

class Student extends Person{ } //学生

但是我们现在要限制  Person类 只能被这三个类继承,不能被其他类继承,需要这么做。

//添加sealed参数,permits后面跟上只能被继承的子类名称
public sealed class Person permits  Teacher, Worker, Student{ } //人

//子类可以被修饰为 final
final class Teacher extends Person { }//教师

//子类可以被修饰为 non-sealed,此时 Worker类就成了普通类,谁都可以继承它
non-sealed class Worker extends Person { }  //工人
//任何类都可以继承Worker
class AnyClass extends Worker{}

//子类可以被修饰为 sealed,同上
sealed class Student extends Person permits MiddleSchoolStudent,GraduateStudent{ } //学生


final class MiddleSchoolStudent extends Student { }  //中学生

final class GraduateStudent extends Student { }  //研究生

很强很实用的一个特性,可以限制类的层次结构。

二、JEP 371: Hidden Classes( 隐藏类) 

该提案通过启用标准 API 来定义 无法发现 且 具有有限生命周期 的隐藏类,从而提高 JVM 上所有语言的效率。JDK内部和外部的框架将能够动态生成类,而这些类可以定义隐藏类。通常来说基于JVM的很多语言都有动态生成类的机制,这样可以提高语言的灵活性和效率。 

  • 隐藏类天生为框架设计的,在运行时生成内部的class。 
  • 隐藏类只能通过反射访问,不能直接被其他类的字节码访问。 
  • 隐藏类可以独立于其他类加载、卸载,这可以减少框架的内存占用。 

Hidden Classes是什么呢? 

Hidden Classes就是不能直接被其他class的二进制代码使用的class。Hidden Classes主要被一些框架用来生成运行时类,但是这些类不是被用来直接使用的,而是通过反射机制来调用。 

比如在JDK8中引入的lambda表达式,JVM并不会在编译的时候将lambda表达式转换成为专门的类,而是在运行时将相应的字节码动态生成相应的类对象。 

另外使用动态代理也可以为某些类生成新的动态类。 

  那么我们希望这些动态生成的类需要具有什么特性呢? 

  1. 不可发现性。 因为我们是为某些静态的类动态生成的动态类,所以我们希望把这个动态生成的类看做是静态类的一部分。所以我们不希望除了该静态类之外的其他机制发现。 
  1. 访问控制。 我们希望在访问控制静态类的同时,也能控制到动态生成的类。 
  1. 生命周期。 动态生成类的生命周期一般都比较短,我们并不需要将其保存和静态类的生命周期一致。 

API的支持 

所以我们需要一些API来定义无法发现的且具有有限生命周期的隐藏类。这将提高所有基于JVM的语言实现的效率。 

比如: 

java.lang.reflect.Proxy可以定义隐藏类作为实现代理接口的代理类。 

java.lang.invoke.StringConcatFactory可以生成隐藏类来保存常量连接方法; 

java.lang.invoke.LambdaMetaFactory可以生成隐藏的nestmate类,以容纳访问封闭变量的lambda主体; 

普通类是通过调用ClassLoader::defineClass创建的,而隐藏类是通过调用Lookup::defineHiddenClass创建的。这使JVM从提供的字节中派生一个隐藏类,链接该隐藏类,并返回提供对隐藏类的反射访问的查找对象。调用程序可以通过返回的查找对象来获取隐藏类的Class对象。 

三、Pattern Matching for instanceof (Second Preview) instanceof 自动匹配模式 

在Java 14中作为预览语言功能引入的instanceof模式匹配,在Java 15中处于第二次预览,而没有任何更改。

此特性我在java14新特性中写过,详情参考:java14新特性

旧写法: 

// 先判断类型
if (obj instanceof String) { 
    // 然后转换 
    String s = (String) obj; 
    // 然后才能使用 
} 

新写法:( 自动匹配模式) 

if (obj instanceof String s) {
    // 如果类型匹配 直接使用 
} else { 
    // 如果类型不匹配则不能直接使用 
} 

四、ZGC: A Scalable Low-Latency Garbage Collector (Production)  ZGC 功能转正 

关注底层优化的小伙伴可以多注重此处。更多请看java14新特性之更多--ZGC

ZGC是Java 11引入的新的垃圾收集器(JDK9以后默认的垃圾回收器是G1),经过了多个实验阶段,自此终于成为正式特性。 

自 2018 年以来,ZGC 已增加了许多改进,从并发类卸载、取消使用未使用的内存、对类数据共享的支持到改进的 NUMA 感知。此外,最大堆大小从 4 TB 增加到 16 TB。支持的平台包括 Linux、Windows 和 MacOS。 

ZGC是一个重新设计的并发的垃圾回收器,通过减少 GC 停顿时间来提高性能。 

但是这并不是替换默认的GC,默认的GC仍然还是G1;之前需要通过-XX:+UnlockExperimentalVMOptions -XX:+UseZGC来启用ZGC,现在只需要-XX:+UseZGC就可以。相信不久的将来它必将成为默认的垃圾回收器。 

相关的参数有ZAllocationSpikeTolerance、ZCollectionInterval、ZFragmentationLimit、ZMarkStackSpaceLimit、ZProactive、ZUncommit、ZUncommitDelay ZGC-specific JFR events(ZAllocationStall、ZPageAllocation、ZPageCacheFlush、ZRelocationSet、ZRelocationSetGroup、ZUncommit)也从experimental变为product .

五、JEP 378:文本块功能转正 

Text Blocks首次是在JDK 13中以预览功能出现的,然后在JDK 14中又预览了一次,终于在JDK 15中被确定下来,可放心使用了。 

之前写java14的时候已经写过了,主要意思就是 可以把 sql、html、json、文章,直接丢到""" """ 里面,保留之前的格式,需要注意的是 length会在最后多出一个空格换行。瞄一眼

package com.hermanwang.java1;

import org.junit.Test;

/**
 * @author hermanwang
 * @create 2020-10-24
 */
public class TextBlocksTest {
    @Test
    public void test1(){
        // 之前的写法
        String text1 = "The Sound of silence\n" +
                "Hello darkness, my old friend\n" +
                "I've come to talk with you again\n" +
                "Because a vision softly creeping\n" +
                "Left its seeds while I was sleeping\n" +
                "And the vision that was planted in my brain\n" +
                "Still remains\n" +
                "Within the sound of silence";

        System.out.println(text1);

        //jdk13中的新特性:
        String text2 = """
                The Sound of silence
                Hello darkness, my old friend
                I've come to talk with you again
                Because a vision softly creeping
                Left its seeds while I was sleeping
                And the vision that was planted in my brain
                Still remains
                Within the sound of silence\
                """;
        System.out.println();
        System.out.println(text2);

        System.out.println(text1.length());
        System.out.println(text2.length());
    }

    //html
    @Test
    public void test2(){
        String html1 = "<html lang=\"en\">\n" +
                "<head>\n" +
                "    <meta charset=\"UTF-8\">\n" +
                "    <title>java14新特性</title>\n" +
                "</head>\n" +
                "<body>\n" +
                "    <p>hello,atguigu</p>\n" +
                "</body>\n" +
                "</html>";
        //jdk13中的新特性:
        String html2 = """
                <html lang="en">
                <head>
                    <meta charset="UTF-8">
                    <title>java14新特性</title>
                </head>
                <body>
                    <p>hello,atguigu</p>
                </body>
                </html>
                """;
    }

    //json
    @Test
    public void test3() {
        //jdk13之前的写法
        String myJson = "{\n" +
                "    \"name\":\"Song Hongkang\",\n" +
                "     \"address\":\"www.atguigu.com\",\n" +
                "    \"email\":\"[email protected]\"\n" +
                "}";
        System.out.println(myJson);

        //jdk13的新特性
        String myJson1 = """
                {
                    "name":"Song Hongkang",
                     "address":"www.atguigu.com",
                    "email":"[email protected]"
                }""";
        System.out.println(myJson1);
    }

    //sql
    @Test
    public void test4(){
        String sql = "SELECT id,NAME,email\n" +
                "FROM customers\n" +
                "WHERE id > 4\n" +
                "ORDER BY email DESC";

        //jdk13新特性:
        String sql1 = """
                SELECT id,NAME,email
                FROM customers
                WHERE id > 4
                ORDER BY email DESC
                """;
    }
    //jdk14新特性
    @Test
    public void test5(){
        String sql1 = """
                SELECT id,NAME,email
                FROM customers
                WHERE id > 4
                ORDER BY email DESC
                """;
        System.out.println(sql1);

        // \:取消换行操作
        // \s:表示一个空格
        String sql2 = """
                SELECT id,NAME,email \
                FROM customers\s\
                WHERE id > 4 \
                ORDER BY email DESC\
                """;
        System.out.println(sql2);
        System.out.println(sql2.length());
    }
}

六、JEP 384Records Class(预览) 

Records Class 也是第二次出现的预览功能,它在 JDK 14 中也出现过一次了,使用 Record 可以更方便的创建一个常量类,使用的前后代码对比如下。  

  • 当你用Record 声明一个类时,该类将自动拥有以下功能: 
  • 获取成员变量的简单方法,以上面代码为例 name() 和 partner() 。注意区别于我们平常getter的写法。 
  • 一个 equals 方法的实现,执行比较时会比较该类的所有成员属性 
  • 重写 equals 当然要重写 hashCode 
  • 一个可以打印该类所有成员属性的 toString 方法。 
  • 请注意只会有一个构造方法。

旧写法:

package com.hermanwang.java1;

import java.util.Objects;

public class Point {

        private final int x;
        private final int y;
        Point(int x, int y) {
            this.x = x;
            this.y = y;
        }
        int x() {
            return x;
        }
        int y() {
            return y;
        }
        public boolean equals(Object o) {
            if (!(o instanceof Point))
                return false;
            Point other = (Point) o;
            return other.x == x && other.y == y;
        }

        public int hashCode() {
            return Objects.hash(x, y);
        }
        public String toString() {
            return String.format("Point[x=%d,y=%d]", x,y);
        }
}

新写法: 

record Point(int x, int y) {} 

record其他特性如下:

package com.hermanwang.java1;

/**
 * @author hermanwang
 * @create 2020-10-24
 */
public record Customer(String name,Customer partner) {
    //还可以声明构造器、静态的变量、静态的方法、实例方法

    public Customer(String name){
        this(name,null);
    }

    public static String info;

    public static void show(){
        System.out.println("我是一个客户");
    }

    public void showName(){
        System.out.println("我的名字是:" + name());
    }

    //不可以在Record中定义实例变量
//    public int id;

}

//Record不可以声明为abstract的
//abstract record User(){}

//Record不可以显式的继承于其他类
//record User() extends Thread{}

好了  至此,主要的六个新特性已经完了,剩下的是 其他的不是很重要的8个新特性。

以下特性仅了解即可。

七、JEP 339Edwards-Curve Digital Signature AlgorithmEdDSA 数字签名算法) 

这是一个新的功能。 

新加入基于Edwards-Curve数字签名算法(EdDSA-Edwards-Curve Digital Signature Algorithm)的加密签名,即爱德华兹曲线数字签名算法。 在许多其它加密库(如 OpenSSL 和 BoringSSL)中得到支持。 

与 JDK 中的现有签名方案相比,EdDSA 具有更高的安全性和性能,因此备受关注。它已经在OpenSSL和BoringSSL等加密库中得到支持,在区块链领域用的比较多。 

EdDSA是一种现代的椭圆曲线方案,具有JDK中现有签名方案的优点。EdDSA将只在SunEC提供商中实现。 

八、JEP 373:Reimplement the Legacy DatagramSocket API(重新实现 DatagramSocket API) 

新的计划是JEP 353的后续,该方案重新实现了遗留的套接字API。 

java.net.datagram.Socket和java.net.MulticastSocket的当前实现可以追溯到JDK 1.0,那时IPv6还在开发中。因此,当前的多播套接字实现尝试调和IPv4和IPv6难以维护的方式。 

  • 通过替换 java.net.datagram 的基础实现,重新实现旧版 DatagramSocket API。 
  • 更改java.net.DatagramSocket 和 java.net.MulticastSocket 为更加简单、现代化的底层实现。提高了 JDK 的可维护性和稳定性。 

通过将java.net.datagram.Socket和java.net.MulticastSocket API的底层实现替换为更简单、更现代的实现来重新实现遗留的DatagramSocket API。 

新的实现:1.易于调试和维护;2.与Project Loom中正在探索的虚拟线程协同。

九、JEP 374: Disable and Deprecate Biased Locking 禁用偏向锁定 

 在默认情况下禁用偏向锁定,并弃用所有相关命令行选项。目标是确定是否需要继续支持偏置锁定的 高维护成本 的遗留同步优化, HotSpot虚拟机使用该优化来减少非竞争锁定的开销。 尽管某些Java应用程序在禁用偏向锁后可能会出现性能下降,但偏向锁的性能提高通常不像以前那么明显。 

该特性默认禁用了biased locking(-XX:+UseBiasedLocking),并且废弃了所有相关的命令行选型(BiasedLockingStartupDelay, BiasedLockingBulkRebiasThreshold, BiasedLockingBulkRevokeThreshold, BiasedLockingDecayTime, UseOptoBiasInlining, PrintBiasedLockingStatistics and PrintPreciseBiasedLockingStatistics) 

十、JEP 379:Shenandoah:低暂停时间垃圾收集器 转正 

Shenandoah垃圾回收算法终于从实验特性转变为产品特性,这是一个从 JDK 12 引入的回收算法,该算法通过与正在运行的 Java 线程同时进行疏散工作来减少 GC 暂停时间。Shenandoah 的暂停时间与堆大小无关,无论堆栈是 200 MB 还是 200 GB,都具有相同的一致暂停时间。 

怎么形容Shenandoah和ZGC的关系呢?异同点大概如下: 

  • 相同点:性能几乎可认为是相同的 
  • 不同点:ZGC是Oracle JDK的。而Shenandoah只存在于OpenJDK中,因此使用时需注意你的JDK版本 

打开方式:使用-XX:+UseShenandoahGC命令行参数打开。 

Shenandoah在JDK12被作为experimental引入,在JDK15变为Production;之前需要通过-XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC来启用,现在只需要-XX:+UseShenandoahGC即可启用 

十一、JEP 383: Foreign-Memory Access API 外部存储器访问 API(孵化器版) 

目的是引入一个 API,以允许 Java 程序安全、有效地访问 Java 堆之外的外部存储器。如本机、持久和托管堆。 

有许多Java程序是访问外部内存的,比如Ignite和MapDB。 该API将有助于避免与垃圾收集相关的成本以及与跨进程共享内存以及通过将文件映射到内存来序列化和反序列化内存内容相关的不可预测性 。该Java API目前没有为访问外部内存提供令人满意的解决方案。但是在新的提议中,API不应该破坏JVM的安全性。 

Foreign-Memory Access API在JDK14被作为incubating API引入,在JDK15处于Second Incubator,提供了改进。 

十二、JEP 381Remove the Solaris and SPARC Ports (移除 Solaris SPARC 端口) 

删除对Solaris/SPARC、Solaris/x64和Linux/SPARC端口的源代码和构建支持,在JDK 14中被标记为废弃,在JDK15版本正式移除。 许多正在开发的项目和功能(如Valhalla、Loom和Panama)需要进行重大更改以适应CPU架构和操作系统特定代码。 

近年来,Solaris 和 SPARC 都已被 Linux 操作系统和英特尔处理器取代。放弃对 Solaris 和 SPARC 端口的支持将使 OpenJDK 社区的贡献者能够加速开发新功能,从而推动平台向前发展。 

十三、JEP 372Remove the Nashorn JavaScript Engine  

Nashorn是在JDK提出的脚本执行引擎,该功能是 2014 年 3 月发布的 JDK 8 的新特性。在JDK11就已经把它标记为废弃了,JDK15完全移除。 

在JDK11中取以代之的是GraalVM。GraalVM是一个运行时平台,它支持Java和其他基于Java字节码的语言,但也支持其他语言,如JavaScript,Ruby,Python或LLVM。性能是Nashorn的2倍以上。 

JDK15移除了Nashorn JavaScript Engine及jjs 命令行工具。具体就是jdk.scripting.nashorn及jdk.scripting.nashorn.shell这两个模块被移除了。 

十四、JEP 385:Deprecate RMI Activation for Removal 

RMI Activation被标记为Deprecate,将会在未来的版本中删除。RMI激活机制是RMI中一个过时的部分,自Java 8以来一直是可选的而非必选项。RMI激活机制增加了持续的维护负担。RMI的其他部分暂时不会被弃用。 

RMI jdk1.2引入,EJB在RMI系统中,我们使用延迟激活。延迟激活将激活对象推迟到客户第一次使用(即第一次方法调用)之前。 既然RMI Activation这么好用,为什么要废弃呢? 

因为对于现代应用程序来说,分布式系统大部分都是基于Web的,web服务器已经解决了穿越防火墙,过滤请求,身份验证和安全性的问题,并且也提供了很多延迟加载的技术。 

所以在现代应用程序中,RMI Activation已经很少被使用到了。并且在各种开源的代码库中,也基本上找不到RMI Activation的使用代码了。 为了减少RMI Activation的维护成本,在JDK8中,RMI Activation被置为可选的。现在在JDK15中,终于可以废弃了。 

完。测试代码地址:https://github.com/cyberHermanwang/Java15Feature

感谢尚硅谷!

猜你喜欢

转载自blog.csdn.net/cyberHerman/article/details/109253931