jdk17新特性

2023-09-20 17:18:57

JDK17新特性

jdk17下载地址:https://download.oracle.com/java/17/latest/jdk-17_windows-x64_bin.exe

JDK 17 文档 - 首页 (oracle.com)

垃圾回收器(Z Garbage Collector)

在这里插入图片描述

概述

JDK17引入名为ZGC(Z Garbage Collector)是一种低延迟的垃圾回收器。是JDK 11引入的一项实验性功能,并在JDK 15中成为稳定特性。

它旨在减少应用程序的停顿时间,使得即使在大内存堆上也能保持非常短的垃圾收集暂停时间。暂停时间与正在使用的堆大小无关。ZGC支持从8MB到16TB的堆大小。

Z 垃圾回收器使用命令行选项 启用。-XX:+UseZGC

设置堆大小

尽管ZGC在降低停顿时间方面取得了显著的改进,但这并不意味着它适用于所有场景。在某些情况下,特别是对于小内存堆或强调极致吞吐量的应用程序,其他垃圾收集器可能更合适。因此,在选择垃圾收集器时,还需要综合考虑应用程序的性质和需求。

设置并发GC线程数

想要查看的第二个调整选项是 设置并发 GC 线程数 .ZGC具有自动选择此数字的启发式方法。这种启发式方法通常效果很好,但根据应用程序的特征,可能需要进行调整。此选项基本上决定了应该给 GC 多少 CPU 时间。给它太多,GC 将从应用程序中窃取太多的 CPU 时间。给它太少,应用程序分配垃圾的速度可能会快于 GC 收集它的速度。(-XX:ConcGCThreads)

一个清洁器的简单示例。它执行以下操作:

  1. 定义一个清理操作类,该类 初始化清理操作并定义清洁操作本身(通过 重写方法)。State``State::run()

  2. 创建 的实例。Cleaner

  3. 使用此实例 ,注册对象和清理操作(的实例)。Cleaner``myObject1``State

  4. 确保垃圾回收器安排清理程序和 在示例结束之前执行清理操作, 示例:

    State::run()
    
    1. 设置为 确保无法访问它。请参阅myObject1``null
    2. 循环中的调用以触发 垃圾回收清理。
import java.lang.ref.Cleaner;

public class CleanerExample {
    
    // This Cleaner is shared by all CleanerExample instances
    private static final Cleaner CLEANER = Cleaner.create();
    private final State state;

    public CleanerExample(String id) {
        state = new State(id);
        CLEANER.register(this, state);
    }

    // Cleaning action class for CleanerExample
    private static class State implements Runnable {
        final private String id;

        private State(String id) {
            this.id = id;
            System.out.println("Created cleaning action for " + this.id);
        }

        @Override
        public void run() {
            System.out.println("Cleaner garbage collected " + this.id);
        }
    }

    public static void main(String[] args) {
        CleanerExample myObject1 = new CleanerExample("myObject1");

        // Make myObject1 unreachable
        myObject1 = null;

        System.out.println("-- Give the GC a chance to schedule the Cleaner --");
        for (int i = 0; i < 100; i++) {
            
            // Calling System.gc() in a loop is usually sufficient to trigger
            // cleanup in a small program like this.
            System.gc();
            try {
                Thread.sleep(1);
            } catch (InterruptedException e) {}
        }
        System.out.println("-- Finished --");
    }
}

输出内容

Created cleaning action for myObject1
-- Give the GC a chance to schedule the Cleaner --
Cleaner garbage collected myObject1
-- Finished --

该代码示例演示了Java中的Cleaner类的用法。

Cleaner类是Java 9引入的一个新特性,用于实现在对象被垃圾回收之前执行必要的清理操作。

这段代码定义了一个CleanerExample类,其中包含一个静态的Cleaner实例和一个私有的State内部类,实现了Runnable接口。

在CleanerExample的构造函数中,每次创建实例时都会注册当前对象和其状态(State)到Cleaner中。在State的构造函数中,会打印出创建清理操作的信息。

在main方法中,首先创建了一个CleanerExample实例。然后将myObject1设置为null,使其变得不可达。

接下来,进入一个循环并在循环中调用System.gc(),以尝试手动触发垃圾回收。在每次循环迭代中,通过调用Thread.sleep()来暂停一小段时间,给垃圾回收器调度Cleaner的机会。

最后,程序输出"-- Finished --"表示程序执行结束。

特点

  • 低停顿时间:ZGC的主要目标是将垃圾收集暂停时间控制在10毫秒以下,甚至更低。这对于需要快速响应的应用程序和大型内存堆非常重要。
  • 回收整个堆:ZGC可以回收整个Java堆,而不仅仅是部分堆区域。这使得它能够处理非常大的内存堆,达到数TB级别。
  • 并发垃圾收集:ZGC使用并发线程来执行垃圾收集操作,允许垃圾收集和应用程序执行同时进行,从而减少了停顿时间。
  • 基于读屏障:ZGC使用了一种基于读屏障(Read Barrier)的技术,来记录对象引用的读取操作,以便在并发清除过程中保证引用的正确性。
  • 可伸缩性:ZGC在设计上注重可伸缩性,能够适应不同规模的应用程序和硬件环境,并能够充分利用多核处理器。

注意: 尽管ZGC在降低停顿时间方面取得了显著的改进,但这并不意味着它适用于所有场景。在某些情况下,特别是对于小内存堆或强调极致吞吐量的应用程序,其他垃圾收集器可能更合适。因此,在选择垃圾收集器时,还需要综合考虑应用程序的性质和需求。

Switch表达式

在Java 14和Java 15中,已经引入了Switch表达式的初始版本。而在JDK 17中,Switch表达式得到了一些改进和增强,包括以下新特性:

  1. 简化的Switch表达式:在JDK 17中,可以使用简化的Switch表达式来替代传统的Switch语句。这意味着Switch表达式可以像其他表达式一样返回一个值,无需使用break语句,并且每个分支只需要使用"->"符号来分隔条件和代码块。

    示例:

    int dayOfWeek = 5;
    String dayType = switch (dayOfWeek) {
        case 1, 2, 3, 4, 5 -> "工作日";
        case 6, 7 -> "休息日";
        default -> throw new IllegalArgumentException("无效的星期");
    };
    System.out.println(dayType);  // 输出:工作日
    

    jdk8编写

    int dayOfWeek = 5;
    String dayType;
    switch (dayOfWeek) {
        case 1:
        case 2:
        case 3:
        case 4:
        case 5:
            dayType = "工作日";
            break;
        case 6:
        case 7:
            dayType = "休息日";
            break;
        default:
            throw new IllegalArgumentException("无效的星期");
    }
    System.out.println(dayType);  // 输出:无效的星期
    
    
  2. 新增的Pattern匹配:在JDK 17中,Switch表达式还支持对Pattern进行匹配。这使得我们可以使用Switch表达式来处理更复杂的模式匹配操作,例如对类型、枚举常量等进行匹配。

    示例:

    Object obj = "Hello";
    int length = switch (obj) {
        case String s -> s.length();
        case Integer i && i > 0 -> i;
        case int[] arr && arr.length > 0 -> arr.length;
        default -> -1;
    };
    System.out.println(length);  // 输出:5
    

    jdk8编写

    Object obj = "Hello";
    int length;
    if (obj instanceof String) {
        String s = (String) obj;
        length = s.length();
    } else if (obj instanceof Integer && ((Integer) obj) > 0) {
        int i = (Integer) obj;
        length = i;
    } else if (obj instanceof int[] && ((int[]) obj).length > 0) {
        int[] arr = (int[]) obj;
        length = arr.length;
    } else {
        length = -1;
    }
    System.out.println(length);  // 输出:5
    
    
  3. 简化的Lambda类型:在JDK 17中,Switch表达式还支持使用"->"符号来指定Lambda表达式的类型。这使得我们可以更简洁地定义Switch表达式中的Lambda表达式。

    示例:

    int number = 4;
    String numberType = switch (number) {
        case 1 -> "One";
        case 2 -> "Two";
        case 3 -> "Three";
        default -> {
            yield "Other";
        }
    };
    System.out.println(numberType);  // 输出:Other
    

jdk8编写

int number = 4;
String numberType;
switch (number) {
    case 1:
        numberType = "One";
        break;
    case 2:
        numberType = "Two";
        break;
    case 3:
        numberType = "Three";
        break;
    default:
        numberType = "Other";
        break;
}
System.out.println(numberType);  // 输出:Other

Switch表达式的新特性需要Java 17或更高版本才能使用。并且在使用Switch表达式时,仍然需要确保每个分支都能够处理所有可能的情况,否则需要在最后添加default分支来处理未匹配到的情况。

sealed关键字

原文在这里插入图片描述

概述

sealed 类是 JDK 17 中引入的一个新特性,它通过控制类的直接子类来提供更严格的类继承关系,并对类层次结构进行限制。这有助于提高代码的可读性和可维护性,并在特定领域建模中非常有用。它通过控制类的直接子类来提供更严格的类继承关系,并对类层次结构进行限制。这有助于提高代码的可读性和可维护性,并在特定领域建模中非常有用。

例如:

public sealed class Student permits StudentSon1, StudentSon2 {
    // 父类定义的共享属性和方法
}

final class StudentSon1 extends Student {
    // 圆形特定的属性和方法
}

final class StudentSon2 extends Student {
    // 矩形特定的属性和方法
}

解释:

通过sealed关键字定义的Student类,只能被permits关键字列出的StudentSon1,StudentSon2类来继承,其他类无法直接继承Student类,负责编译错误

这样的设计有助于受限制继承关系,使得只有特定的StudentSon1和StudentSon2来继承Student父类。

这种模式可以在建模特定领域或实现特定抽象时非常有用,因为它能提供更严格的类层次结构,增加代码的可读性和可维护性。

特点

  • 当一个类被声明为sealed类时,这意味着在声明这个类时已经知道了它的所有直接子类,并且不希望或需要有其他直接子类。这种对类直接子类的明确和详尽控制在用类层次来建模领域中的值类型时非常有用,而不仅仅是作为代码继承和重用的机制。直接子类本身也可以声明为sealed类,以进一步控制类层次结构。
  • 一个类可以被声明为final类,如果该类的定义已经完整,不希望或需要有任何子类。final类永远不会有任何子类,因此final类的方法也不会被覆盖。
  • 如果一个类有一个sealed的直接超类或者一个sealed的直接超接口,而且没有明确或隐式地声明为final、sealed或non-sealed,那么这将是一个编译时错误。

permits关键字

permits 是用于定义一个 sealed 类的子类集合的关键字。在一个 sealed 类的声明中,可以使用 permits 关键字来列出一组允许的子类,这些子类可以继承该 sealed 类。

当一个类被声明为 sealed 类时,它必须显式列出其所允许的所有直接子类。这个列表通过使用 permits 关键字来定义,其后跟随该 sealed 类所允许的子类名称或类型。例如:

public sealed class Animal permits Cat, Dog, Fish {
    // 类主体
}

Animal 是一个 sealed 类,它允许的子类分别是 Cat、Dog 和 Fish。

需要注意的是,使用 permits 关键字列出的子类必须是 sealed 类、final 类或 non-sealed 类。如果不是这些类型之一,那么会出现编译时错误。

permits 是 Java 中用于定义 sealed 类的允许子类集合的关键字,它可以帮助开发人员更加精确地控制类的继承关系,提高代码的可读性和可维护性。

原文:在这里插入图片描述

/*
定义一个sealed类,在permits列表中出现编译错误p.B
正确的写法是使用完整的包名前缀,例如 package.B
sealed class A 表示类 A 是一个 sealed 类,但由于permits列表中的子句错误,代码无法通过编译。
*/
sealed class A permits B, C, p.B {} // error 
//类 B 是一个非 sealed 类,它继承自类 A。由于 A 是 sealed 类,所以 B 可以作为 A 的子类进行扩展。
non-sealed class B extends A {} 
//类 C 是一个非 sealed 类,也继承自类 A。与类 B 一样,C 作为 A 的子类进行扩展。
non-sealed class C extends A {}
更多推荐

【数据库入门到精通】mysql的存储过程实战

前言🏠个人主页:我是沐风晓月🧑个人简介:大家好,我是沐风晓月,双一流院校计算机专业,阿里云社区专家博主😉😉💕座右铭:先努力成长自己,再帮助更多的人,一起加油进步🍺🍺🍺💕欢迎大家:这里是CSDN,我总结知识的地方,喜欢的话请三连,有问题请私信😘可以关注我的云原生社区:云原生社区也可以关注我的英语社区:

Input子系统 - Kernel驱动程序 - Android

Input子系统-Kernel驱动程序-Android1、Input子系统相关定义1.1代码位置1.2input_dev结构体:表示输入设备1.3input_handler结构体:structinput_handler-implementsoneofinterfacesforinputdevices1.4input_h

elasticsearch基础篇

目录1.mysql与elasticsearch2.索引库操作2.1.mapping映射属性2.2.索引库的CRUD2.2.1.创建索引库和映射2.2.2.查询索引库2.2.3.修改索引库2.2.4.删除索引库2.2.5.总结3.文档操作3.1.新增文档3.2.查询文档3.3.删除文档3.4.修改文档3.4.1.全量修改

《C++API设计》读书笔记(3):模式

本章内容本章涵盖了一些与C++API设计相关的设计模式和惯用法。“设计模式(DesignPattern)”表示软件设计问题的一些通用解决方案。该术语来源于《设计模式:可复用面向对象软件的基础》(DesignPatterns:ElementsofReusableObject-OrientedSoftware)本书不会涵盖

使用Python进行健身手表数据分析

健身手表(FitnessWatch)数据分析涉及分析健身可穿戴设备或智能手表收集的数据,以深入了解用户的健康和活动模式。这些设备可以跟踪所走的步数、消耗的能量、步行速度等指标。本文将带您完成使用Python进行FitnessWatch数据分析的任务。FitnessWatch数据分析是健康和保健领域企业的重要工具。通过分

C 语言网络编程 — NAT 网关运行原理

目录文章目录目录NATNATGW实现原理NAT技术的类型NAT技术的基本原理NAT技术的连接跟踪功能NAPT技术的基本原理NAPT技术的连接跟踪功能NATServerNAT穿透LinuxiptablesNATSNATDNATNAPTNATNAT(NetworkAddressTranslation,网络地址转换)是一种L

基于Java+SpringBoot+vue前后端分离小徐影城管理系统设计实现

博主介绍:✌全网粉丝30W+,csdn特邀作者、博客专家、CSDN新星计划导师、Java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌🍅文末获取源码联系🍅👇🏻精彩专栏推荐订阅👇🏻不然下次找不到哟2022-2024年最全的计算机软件毕业设计选题

Java笔记:Java虚拟机的指令

1.字节码指令集1.1概述Java虚拟机的指令由一个字节长度的、代表着某种特定操作含义的数字(称为操作码,Opcode)以及跟随其后的零至多个代表此操作所需参数(称为操作数,Operands)而构成。比如:字节码助记符指令含义0x00nop什么都不做0x01aconst_null将null推送至栈顶0x02iconst

深度思考计算机网络面经之三

计算机网络.1说说你对tcp滑动窗口的理解TCP滑动窗口是TCP协议流量控制的一个重要机制。它的主要目的是确保发送方不会因为发送太多数据而使接收方不堪重负。下面我会详细地描述滑动窗口的概念:窗口的大小:滑动窗口的大小(以字节为单位)表示发送方在等待确认之前可以发送的最大数据量。该大小可以是固定的,但在现代的TCP实现中

【计算机基础知识】计算机的概念

欢迎来到我的:世界希望作者的文章对你有所帮助,有不足的地方还请指正,大家一起学习交流!目录前言1.计算机的概念计算机的发展历程知识拓展:计算机的特点计算机的分类2.计算机的应用计算机的发展趋势知识拓展:总结前言美国数学家香农说过:信息是能够消除不确定性的东西,也就是说信息能消除事物的不确定性,把不确定变成确定性;1.计

用户参与策略:商城小程序的营销推广

在现代数字化时代,商城小程序已成为许多企业推广产品和服务的重要工具。然而,要确保小程序的成功,不仅需要吸引用户访问,还需要采取有效的用户参与策略,以建立持久的客户关系。本文将深入探讨用户参与策略,以推广商城小程序并提高用户忠诚度。第一部分:用户参与的重要性建立品牌忠诚度用户参与是建立品牌忠诚度的关键。通过积极互动和参与

热文推荐