细说 Java 14 新特性

前言

JDK 14 也就是我们说的 Java14 发布了,那你已经了解到了它有哪些新的特性了吗?

这次在新的 Java14 中加入了非常多的语法糖,这可以使得我们在编程过程中更加的快捷,写出来的代码也会更加简介一些。话不多说,我们马上来看看这次更新了哪些新特性吧!

增强 instanceOf 类型推断

在 Java 14 之前我们需要这样写代码:

        Object object  = someOneObj();
        if(object instanceof String){
            boolean isContainsA = ((String) object).contains("A");
        }

现在我们只需要这样写:

        Object object = someOneObj();
        if (object instanceof String str) { // 注意这里更换了变量名
            boolean isContainsA = str.contains("A");
        }
        // 还能继续加入判断条件
        if (object instanceof String str && str.contains("A")) {
            System.out.println(str);
        }

增强 switch case 代码块

以前我们写 switch case 是这样的:

        String day = getDay();
        switch (day) {
            case "周一":
            case "周二":
                System.out.println("这里是周一和周二");
                break;
            case "周三":
                System.out.println("这里是周三");
                break;
            case "周四":
                System.out.println("这里是周四");
                break;
            default:
                System.out.println("这里是周五六日");
                break;
        }

Java 14 我们可以这样写啦:

        String day = getDay();
        switch (day) {
            case "周一", "周二" -> System.out.println("这里是周一和周二");
            case "周三" -> System.out.println("这里是周三");
            case "周四" -> System.out.println("这里是周四");
            default -> System.out.println("这里是周五六日");
        }

还可以新增返回值哦:

        boolean isWorkday = switch (day) {
            case "周六", "周日" -> false;
            default -> true;
        };

甚至可以利用yield把返回值挂起:

        boolean isWorkday = switch (day) {
            case "周六", "周日" -> false;
            default -> {
                boolean isWeekend = isWeekend(day);
                yield isWeekend;// 这2行可以合并省略变量,为了解释留下的
            }
        };

新增构造函数关键字 record

以前我们构造一个 class, 按照规范需要写get,set,equals,hashcode等方法:

public class SomeClass {
    private String stringField;
    private int intField;

    public SomeClass(String stringField, int intField) {
        this.stringField = stringField;
        this.intField = intField;
    }

    public String getStringField() {
        return stringField;
    }

    public void setStringField(String stringField) {
        this.stringField = stringField;
    }

    public int getIntField() {
        return intField;
    }

    public void setIntField(int intField) {
        this.intField = intField;
    }
    
    // 剩下的equals toString hashcode 等方法...
}

现在只需要加入关键字 record 就行了:

record SomeClass(String strFiled, int intFiled) {
// 它会自动生成equals,tostring,hashcode get/set等方法
}

注意:

record 是修饰在 class 名的,不是构造函数,也就是说你不用再写 public class SomeClass 了。

它所有修饰的字段是final类型的,基础数据类型不可以再更改值,但是对象可以更改内部字段。

它默认继承了Record类,所以不能再继承其他类了,所生成的类也是final类型的。

可以继续增加静态属性:

record SomeClass(String strFiled, int intFiled) {
    static int number = 1;
}

字符串块

以前我们写长长的字符串,需要这样写:

        String str = "<html>" +
                "<header>" +
                "</header>" +
                "<body>" +
                "<div>body</div>" +
                "</body>" +
                "</html>";

Java 14 可以实用三个引号作为字符串块了:

        // 注意 """ 之后必须换行
        String str = """
                <html>
                        <header>
                        </header>
                    <body>
                        <div>"body"</div>
                    </body>
                </html>
                """;

增强NPE NullPointerException 错误推断

以前NPE报错只报哪一行:

line 1 User user = someUser();
line 2 user.getChild().getName().someMethod();

比如你收到 line 2 出现了 NPE, 那你知道是user为null呢?还是user的child为null呢?还是他的name为null呢?

现在 Java 14 优化了这个报错,会直接告诉你具体是哪一个属性出现了null:

Exception in thread "main" java.lang.NullPointerException:
        Cannot read field 'user' because 'user.getChild()' is null.
    at Prog.main(Prog.java:5)

Non-Volatile Mapped Byte Buffers

Java NIO(New IO)JDK 1.4以来就存在,FileChannel使用MappedByteBuffer将文件数据的一部分加载到虚拟内存中,然后引入了新的增强,称为Path。Path是一个接口,当我们在java NIO中工作时,它将java.io.File类替换为文件或目录的表示。

现在JEP的目标是在MappedByteBuffer中进行增强,以便non-volatile memory (NVM)中加载文件数据的部分。在这种存储器中,即使像ROM(只读存储器)、Flash存储器、硬盘等存储设备关闭电源,数据也不会丢失/删除;在non-vllatile的情况下,如果像RAM一样关闭电源,数据也不会保留。唯一需要更改的API是FileChannel客户端使用的新枚举,用于请求位于NVM支持的文件系统(而不是传统的文件存储系统)上的文件的映射。

此实现允许通过ByteBuffer将NVM作为堆外资源进行管理。一个相关的增强,JDK-8153111,正在研究对堆数据使用NVM。可能还需要考虑使用NVM来存储JVM元数据。这些不同的NVM管理模式在结合使用时可能不兼容,或者可能只是不合适。该API只能处理高达2GB的映射区域。可能需要修改建议的实现,使其符合JDK-8180628中建议的更改,以克服此限制。

打包工具

Java 14 计划引入打包功能,以简化依赖于各种依赖项的安装过程。有时仅仅提供一个JAR文件是不够的;它必须提供一个适合本地/本机的可安装工具包。打包工具还可以帮助填补其他技术留下的空白。

jpackage工具将Java应用程序捆绑到一个特定于平台的包中,该包包含所需的所有依赖项。作为一组普通的JAR文件或模块集合。支持的特定于平台的包格式包括:

Linux:deb和rpm

macOS:pkg和dmg

Windows:msi和exe

G1 的非均匀存储器访问

非均匀存储器访问(Non-uniform memory accession,NUMA)是一种将微处理器集群配置成多处理系统的方法,可以实现内存的局部共享,提高系统性能,扩展系统能力。

Java 14正计划实现支持NUMA的内存分配,以提高大型计算机上的G1性能。

G1的堆被组织为固定大小区域的集合。一个区域通常是一组物理页面,但是当使用大页面(via-XX:+UseLargePages)时,几个区域可以组成一个物理页面。

如果指定了+XX:+UseNUMA选项,那么当JVM初始化时,区域将均匀地分布在可用的NUMA节点总数上。

JFR 事件流 

Java 14 正计划提供一个API,通过该API,JDK飞行记录器(JFR)收集的数据将连续监视进程内和进程外应用程序。

可以以非流式方式记录相同的事件集,如果可能的话,开销小于1%。因此,事件流将与非流同时执行。

jdk.jfr模块中的jdk.jfr.consumer包扩展了异步订阅事件的功能。

其他特性

废除了 Solaris / SPARC, Solaris / x64, and Linux / SPARC, 并会在以后的版本中彻底移除

移除了CMS垃圾回收器

给windows和macOS新增了特定垃圾回收器

废除了并行清楚和串行GC(ParallelScavenge + SerialOld GC)组合

移除了pack200 相关工具和api

如果感兴趣的童鞋可以上官方网站详细了解哟!

发表评论

您的电子邮箱地址不会被公开。 必填项已用 * 标注

Scroll to Top