[Java Base]Java 8 ~ Java19新特性

简介: [Java Base]Java 8 ~ Java19新特性

资源

📁 JDK-downloads

内容详情

Java 9 ~ 11:

ZGC垃圾回收器

据说这是JDK11最为瞩目的特性,没有之一,是最重磅的升级,那么ZGC的优势在哪里呢?

  • GC暂停时间不会超过10毫秒
  • 既能处理几百兆的小堆,也能处理几个T的大堆
  • 和G1相比,应用吞吐能力不会下降超过15%
  • 为未来的GC功能和利用colord指针以及Load barriers优化奠定了基础

ZGC是一个并发、基于region、压缩型的垃圾收集器,只有root扫描阶段会STW(strop the world,停止所有线程),因此ZGC的停顿时间不会随着堆的增长和存活对象的增长而变长。用法:-XX:UnlockExperimentalVMOptions -XX:+UseZGC

字符串API增强

// 用来判断字符串是不是空字符"“或者trim()之后(” ")为空字符:
isBlank()
//将一个字符串按照行终止符(换行符\n或者回车符\r)进行分割,并将分割为Stream流:
lines()
//按照给定的次数重复串联字符串的内容:
repeat(n)

集合转对应类型的数组

之前想集合转对应的数组很麻烦,要么用迭代;要么用Stream流,现在你可以这样:

         List<String> sampleList = Arrays.asList("张三", "java 11");
         // array = {"张三", "java 11"};
         String[] array = sampleList.toArray(String[]::new);

var可以用于修饰Lambda局部变量

在Java 10中引入的var来进行类型推断。在Java 10中它不能用于修饰Lambda表达式的入参,其实对于一个Lambda表达式来说它入参的类型其实是可以根据上下文推断出来的。拿上面的例子来说,s -> s.startsWith(“j”)中的s肯定是字符串类型,因此在Java 11中var可以用于修饰Lambda局部变量:

   List<String> sampleList = Arrays.asList("张三", "java 11","jack");
        List<String> result = sampleList.stream()
                // 过滤以j开头的字符串
                .filter((@NotNull var s) -> s.startsWith("j"))
                // 同时不包含11的字符串
                .filter(Predicate.not((@NotNull var s) -> s.contains("11")))
                .collect(Collectors.toList());

文件中读写字符串内容更方便

Java 11中可以更轻松地从文件中读取和写入字符串内容了,我们可以通过Files工具类提供的新的静态方法readString和writeString分别进行读写文件的字符串内容,放在之前老麻烦了,特别是对IO流不熟悉的同学来说。现在简单几行就搞定了:

        String dir= "C://yourDir/hello.txt";
// 写入文件
        Path path = Files.writeString(Path.of(dir), "hello java 11");
// 读取文件
            String fileContent = Files.readString(path);
            // hello java 11
        System.err.println(fileContent);

Java 12~17:

文本块
switch表达式
record关键字
sealed classes密封类
instanceof模式匹配
Helpful NullPointerExceptions
日期周期格式化
精简数字格式化支持
Stream.toList()简化

文本块 (Java17)

假设有这样一个场景,我们需要做一个工具。用来自动生成项目文档,文档可以通过浏览器查看,所以最后产出物肯定是一堆html文件。为了让这些html文件更容易读,良好的格式肯定要保持,该换行的换行、该缩进的缩进。
那么,在组织最后内容的时候,你可能就会这样子来写:

String html = 
    "<html>\n" +
    "<body>\n"+
    "  <h1>Java 17新特性:文本块 -0xYGC</h1>\n"+
    "  <p>didispace.com</p>\n"+
    "</body>\n"+
    "</html>\n";
当然,也许你也会改进一下,用StringBuilder或者StringBuffer来优化,但不论用什么来写,都逃不了一些要转义的内容,比如上面拼接内容时候的换行\n。

一旦存在大量要转义内容的时候,也就增加了我们编写代码的复杂度。复杂度越高,我们就越容易犯错。所以,在Java 17中增加了一个新特性:文件块(Text Blocks),来帮助我们更便捷的实现多行字符串文字的处理。
对于上面的字符串内容,Java 17中,我们只需要这样写:

String html = """
    <html>
    <body>
      <h1>Java 17新特性:文本块 -0xYGC</h1>
      <p>didispace.com</p>
    </body>
    </html>
    """;

像这种改进还是特别有用的,比如ES的最新客户端支持DSL部分脚本代码运行, Flink 也支持SQL脚本,以及 Sping Data JPA等等

switch表达式

Java 17版本中switch表达式将允许switch有返回值,并且可以直接作为结果赋值给一个变量,等等一系列的变化。下面有一个switch例子,依赖于给定的枚举值,执行case操作,故意省略break。

    private static void lowVesion(Fruit fruit) {
        switch (fruit) {
            case APPLE, PEAR:
                System.out.println("普通水果");
            case MANGO, AVOCADO:
                System.out.println("进口水果");
            default:
                System.out.println("未知水果");
        }
    }

我们调用这个方法传入一个APPLE,会输出以下结果: 普通水果进口水果未知水果
显然这不是期望的结果,因为我们需要在每个case里添加break防止所有的case都被执行。
Java17可以通过switch表达式来进行简化。将冒号(:)替换为箭头(->),并且switch表达式默认不会失败,所以不需要break。

    private static void withReturnValue(Fruit fruit) {
        String text = switch (fruit) {
            case APPLE, PEAR -> "普通水果";
            case MANGO, AVOCADO -> "进口水果";
            default -> "未知水果";
        };
        System.out.println(text);
    }

也可以直接省略赋值动作直接打印。

    private static void withReturnValue(Fruit fruit) {
        System.out.println(switch (fruit) {
            case APPLE, PEAR -> "普通水果";
            case MANGO, AVOCADO -> "进口水果";
            default -> "未知水果";
        });
    }

如果你想在case里想做不止一件事,比如在返回之前先进行一些计算或者打印操作,可以通过大括号来作为case块,最后的返回值使用关键字yield进行返回。

    private static void withYield(Fruit fruit) {
        String text = switch (fruit) {
            case APPLE, PEAR -> {
                System.out.println("给的水果是: " + fruit);
                yield "普通水果";
            } case MANGO, AVOCADO -> "进口水果";
            default -> "未知水果";
        }; System.out.println(text);
    }

Records关键字(Java14 添加)

record用于创建不可变的数据类。在这之前如果你需要创建一个存放数据的类,通常需要先创建一个Class,然后生成构造方法、getter、setter、hashCode、equals和toString等这些方法,或者使用Lombok来简化这些操作。

通过对类做这样的声明,编译器可以通过自动创建所有方法并让所有字段参与hashCode()等方法。这是JDK 14中的一个预览特性。
使用record关键字可以定义一个记录:

    record Person (String firstName, String lastName) {}

假设有一些场景我们只需要对Person的name和age属性进行打印,在有record之后将会变得非常容易。

PersonRecord p1Record = new PersonRecord(p1.getName(), p1.getAge());
PersonRecord p2Record = new PersonRecord(p2.getName(), p2.getAge());
System.out.println(p1Record);
System.out.println(p2Record);

record 解决了使用类作为数据包装器的一个常见问题。纯数据类从几行代码显著地简化为一行代码。(详见: Java 14 发布了,不使用”class”也能定义类了?还顺手要干掉Lombok! )

封闭类 (Java15)

在Java 15之前,Java认为"代码重用"始终是一个终极目标,所以,一个类和接口都可以被任意的类实现或继承。但是,在很多场景中,这样做是容易造成错误的,而且也不符合物理世界的真实规律。

例如,假设一个业务领域只适用于汽车和卡车,而不适用于摩托车。在Java中创建Vehicle抽象类时,应该只允许Car和Truck类扩展它。通过这种方式,我们希望确保在域内不会出现误用Vehicle抽象类的情况。为了解决类似的问题,在Java 15中引入了一个新的特性——密闭。
想要定义一个密闭接口,可以将sealed修饰符应用到接口的声明中。然后,permit子句指定允许实现密闭接口的类:

    public sealed interface Service permits Car, Truck {     }

通过密闭特性,我们定义出来的Vehicle类只能被Car和Truck继承。

Sping Boot 3.0 已经最低要Java 17了,
2022-06-28 发布的 Jenkins 2.357 和即将发布的 9 月 LTS 版本开始,Jenkins 最低需要 Java 11
Kafka3.0弃用Java 8

日期周期格式化

在Java 17中添加了一个新的模式B,用于格式化DateTime,它根据Unicode标准指示一天时间段。使用默认的英语语言环境,打印一天的几个时刻:

DateTimeFormatter dtf = DateTimeFormatter.ofPattern("B");
System.out.println(dtf.format(LocalTime.of(8, 0)));
System.out.println(dtf.format(LocalTime.of(13, 0)));
System.out.println(dtf.format(LocalTime.of(20, 0)));
System.out.println(dtf.format(LocalTime.of(23, 0)));
System.out.println(dtf.format(LocalTime.of(0, 0)));
  • 输出结果:

in the morningin the afternoonin the eveningat nightmidnight
如果是中文语言环境,则输出结果为:
上午下午晚上晚上午夜

精简数字格式化支持

在NumberFormat中添加了一个工厂方法,可以根据Unicode标准以紧凑的、人类可读的形式格式化数字。

NumberFormat fmt = NumberFormat.getCompactNumberInstance(Locale.ENGLISH, NumberFormat.Style.SHORT);
System.out.println(fmt.format(1000));
System.out.println(fmt.format(100000));
System.out.println(fmt.format(1000000));

输出格式为:1K100K1M
当然还有其他格式:比如Long类型线显示成数值可以为:1 thousand100 thousand1 million

Java 18~19:

JDK 18

🔗 JDK 18 新特性官网

🔗 Java 18 新特性

JDK 19

🔗 Java 19 正式发布,改善多线程、并发编程难度

参考资料 & 致谢

[1] Java 17 新特性:文本块

目录
相关文章
|
23天前
|
Java API 数据处理
Java新特性:使用Stream API重构你的数据处理
Java新特性:使用Stream API重构你的数据处理
Java API 开发者
47 0
|
3月前
|
并行计算 Java API
Java List 集合结合 Java 17 新特性与现代开发实践的深度解析及实战指南 Java List 集合
本文深入解析Java 17中List集合的现代用法,结合函数式编程、Stream API、密封类、模式匹配等新特性,通过实操案例讲解数据处理、并行计算、响应式编程等场景下的高级应用,帮助开发者提升集合操作效率与代码质量。
162 1
|
3月前
|
安全 Java 微服务
Java 最新技术和框架实操:涵盖 JDK 21 新特性与 Spring Security 6.x 安全框架搭建
本文系统整理了Java最新技术与主流框架实操内容,涵盖Java 17+新特性(如模式匹配、文本块、记录类)、Spring Boot 3微服务开发、响应式编程(WebFlux)、容器化部署(Docker+K8s)、测试与CI/CD实践,附完整代码示例和学习资源推荐,助你构建现代Java全栈开发能力。
433 0
|
3月前
|
缓存 安全 Java
Java 并发新特性实战教程之核心特性详解与项目实战
本教程深入解析Java 8至Java 19并发编程新特性,涵盖CompletableFuture异步编程、StampedLock读写锁、Flow API响应式流、VarHandle内存访问及结构化并发等核心技术。结合电商订单处理、缓存系统、实时数据流、高性能计数器与用户资料聚合等实战案例,帮助开发者高效构建高并发、低延迟、易维护的Java应用。适合中高级Java开发者提升并发编程能力。
88 0
|
3月前
|
安全 Java API
Java 17 及以上版本核心特性在现代开发实践中的深度应用与高效实践方法 Java 开发实践
本项目以“学生成绩管理系统”为例,深入实践Java 17+核心特性与现代开发技术。采用Spring Boot 3.1、WebFlux、R2DBC等构建响应式应用,结合Record类、模式匹配、Stream优化等新特性提升代码质量。涵盖容器化部署(Docker)、自动化测试、性能优化及安全加固,全面展示Java最新技术在实际项目中的应用,助力开发者掌握现代化Java开发方法。
146 1
|
3月前
|
IDE Java API
Java 17 新特性与微服务开发的实操指南
本内容涵盖Java 11至Java 17最新特性实战,包括var关键字、字符串增强、模块化系统、Stream API、异步编程、密封类等,并提供图书管理系统实战项目,帮助开发者掌握现代Java开发技巧与工具。
201 1
|
12天前
|
JSON 网络协议 安全
【Java】(10)进程与线程的关系、Tread类;讲解基本线程安全、网络编程内容;JSON序列化与反序列化
几乎所有的操作系统都支持进程的概念,进程是处于运行过程中的程序,并且具有一定的独立功能,进程是系统进行资源分配和调度的一个独立单位一般而言,进程包含如下三个特征。独立性动态性并发性。
60 1
|
12天前
|
JSON 网络协议 安全
【Java基础】(1)进程与线程的关系、Tread类;讲解基本线程安全、网络编程内容;JSON序列化与反序列化
几乎所有的操作系统都支持进程的概念,进程是处于运行过程中的程序,并且具有一定的独立功能,进程是系统进行资源分配和调度的一个独立单位一般而言,进程包含如下三个特征。独立性动态性并发性。
52 2
|
1月前
|
数据采集 存储 弹性计算
高并发Java爬虫的瓶颈分析与动态线程优化方案
高并发Java爬虫的瓶颈分析与动态线程优化方案

热门文章

最新文章