JDK版本特性演变

发布时间 2023-11-27 22:38:31作者: 安浩阳

JDK版本特性演变

官网JEP指数

Jdk 1~8

  1. JDK 1.0(1996年1月)

    • 初版发布。
    • 包含了基本的Java开发工具,如编译器(javac)和解释器(java)。
  2. JDK 1.1(1997年2月)

    • 引入了内部类(Inner Classes)。
    • 支持JavaBeans组件模型。
    • 增加了AWT事件处理模型。
    • 引入了RMI(远程方法调用)和JDBC(Java数据库连接)。
  3. J2SE 1.2(1998年12月)

    • 引入了Swing GUI库,提供更丰富的用户界面。
    • 增加了集合框架。
    • 引入了JNDI(Java命名和目录接口)和JDBC 2.0。
  4. J2SE 1.3(2000年5月)

    • 提高了性能。
    • 引入了HotSpot虚拟机,改进了即时编译器。
    • 加入了Java Naming and Directory Interface(JNDI)。
  5. J2SE 1.4(2002年2月)

    • 引入了正则表达式支持。
    • 加入了NIO(New I/O)包,提供了更强大的I/O操作。
    • 加入了Java Web Start,支持通过Web启动应用程序。
    • 引入了XML解析和XSLT支持。
  6. J2SE 5.0(2004年9月) ,也称为JDK 1.5:

    • 引入了泛型(Generics)。
    • 加入了枚举(Enum)类型。
    • 引入了自动装箱和拆箱。
    • 加入了注解(Annotations)。
    • 引入了可变参数。
    • 加入了JVM监控和管理接口(JMX)。
  7. Java SE 6(2006年12月) ,也称为JDK 1.6:

    • 引入了Java Compiler API。
    • 加入了支持脚本语言的JSR 223(Java Specification Request)。
    • 加入了JDBC 4.0。
    • 引入了Pluggable Annotations。
  8. Java SE 7(2011年7月)

    • 引入了try-with-resources语句,简化资源管理。
    • 加入了Diamond语法,简化泛型的使用。
    • 引入了Fork/Join框架,用于并行编程。
    • 引入了新的文件I/O API(NIO.2)。
  9. Java SE 8 (LTS 版本)(2014年3月)

    • 引入了Lambda表达式,简化代码编写。
    • 加入了新的日期和时间API(java.time)。
    • 引入了新的JavaScript引擎,Nashorn。
    • 加入了PermGen空间的移除,使用元空间(Metaspace)代替。


Jdk 8 (LTS 版本)

新特性:

  1. Lambda 表达式

    Lambda 表达式简单来讲是一个匿名函数,Java 8 允许将函数作为参数传递到方法之中。

  2. Stream流

    提供了对集合数据进行检索和逻辑处理的功能,包括筛选、排序、统计、计数等。可以形象地将其比作 SQL 语句。

  3. Optional

    主要用来处理传入的数据的空指针NullPointerException问题

  4. Interface支持默认与静态方法

    新增default 或 static 关键词来修饰 interface 的方法

    • default 方法是普通实例方法,可以使用 this 关键词调用,可以被子类继承和重写;
    • static 方法与一般类的静态方法类似,无法被子类继承,只能通过 Interface 调用。
  5. 函数式接口

    定义:有且只有一个抽象方法,但可以有多个非抽象方法的接口。

    提供函数式编程,@FunctionalInterface注解只是在编译时起到强制规范定义的作用,不存在也可以

  6. Date-Time API

    这是对java.util.Date强有力的补充,解决了 Date 类的大部分痛点:

    • ​​非线程安全

    • 时区处理麻烦

    • 各种格式化、和时间计算繁琐

    • 设计有缺陷,Date 类同时包含日期和时间;还有一个 java.sql.Date,容易混淆。


Jdk 9

新特性:

  • 模块化
  • 提供了 List.of()、Set.of()、Map.of()和 Map.ofEntries()等工厂方法
  • 接口支持私有方法
  • Optional 类改进
  • 多版本兼容 Jar 包
  • JShell 工具
  • try-with-resources 的改进
  • Stream API 的改进
  • 设置 G1 为 JVM 默认垃圾收集器
  • 支持 http2.0 和 websocket 的 API

重要特性:

  • 模块化开发

    之前:image

    之后:​image

    用法:

    1. 被调用方image

    2. 调用方image


Jdk 10

新特性:

  • 局部变量类型推断,类似 JS 可以通过 var 来修饰局部变量,编译之后会推断出值的真实类型
  • 不可变集合的改进
  • 并行全垃圾回收器 G1,来优化 G1 的延迟
  • 线程本地握手,允许在不执行全局 VM 安全点的情况下执行线程回调,可以
  • 停止单个线程,而不需要停止所有线程或不停止线程
  • Optional 新增 orElseThrow()方法
  • 类数据共享
  • Unicode 语言标签扩展
  • 根证书

重要特性:

  • 通过 var 关键字实现局部变量类型推断,使 Java 语言变成弱类型语言
  • JVM 的 G1 垃圾回收由单线程改成多线程并行处理,降低 G1 的停顿时间。


Jdk 11 (LTS 版本)

新特性:

  • 增加一些字符串处理方法

  • 用于 Lambda 参数的局部变量语法

  • Http Client 重写,支持 HTTP/1.1 和 HTTP/2 ,也支持 websockets

  • 可运行单一 Java 源码文件,如:java Test.java

  • ZGC:可伸缩低延迟垃圾收集器,ZGC 可以看做是 G1 之上更细粒度的内存

    管理策略。由于内存的不断分配回收会产生大量的内存碎片空间,因此需要整理策略防止内存空间碎片化,在整理期间需要将对于内存引用的线程逻辑暂停,这个过程被称为"Stop the world"。只有当整理完成后,线程逻辑才可以继续运行。(并行回收)

  • 支持 TLS 1.3 协议

  • Flight Recorder(飞行记录器),基于 OS、JVM 和 JDK 的事件产生的数据收集框架

  • 对 Stream、Optional、集合 API 进行增强

重要特性:

  • 单文件程序


Jdk 12

新特性:

  • Switch 表达式扩展,可以有返回值
  • 新增 NumberFormat 对复杂数字的格式化
  • 字符串支持 transform、indent 操作
  • 新增方法 Files.mismatch(Path, Path)
  • Teeing Collector
  • 支持 unicode 11
  • Shenandoah GC,新增的 GC 算法
  • G1 收集器的优化,将 GC 的垃圾分为强制部分和可选部分,强制部分会被回收,可选部分可能不会被回收,提高 GC 的效率

重要特性:

  • ​​switch 表达式语法扩展
  • G1 收集器优化
  • 新增 Shenandoah GC 垃圾回收算法


Jdk 13

新特性:

  • Switch 表达式扩展,switch 表达式增加 yield 关键字用于返回结果,作用类似于 return,如果没有返回结果则使用 break
  • 文本块升级,引入了文本块,可以使用"""三个双引号表示文本块,文本块内部就不需要使用换行的转义字符
  • SocketAPI 重构,Socket 的底层实现优化,引入了 NIO
  • FileSystems.newFileSystem 新方法
  • ZGC 优化,增强 ZGC 释放未使用内存,将标记长时间空闲的堆内存空间返还给操作系统,保证堆大小不会小于配置的最小堆内存大小,如果堆最大和最小内存大小设置一样,则不会释放内存还给操作系统

重要特性:

  • ZGC 优化,释放内存还给操作系统
  • socket 底层实现引入 NIO。


Jdk 14

新特性:

  • instanceof 模式匹配,instanceof 类型匹配语法简化,可以直接给对象赋值,如 if(obj instanceof String str),如果 obj 是字符串类型则直接赋值给了 str 变量
  • 引入 Record 类型,类似于 Lombok 的@Data 注解,可以向 Lombok 一样自动生成构造器、equals、getter 等方法;
  • Switch 表达式-标准化
  • 改进 NullPointerExceptions 提示信息,打印具体哪个方法抛的空指针异常,避免同一行代码多个函数调用时无法判断具体是哪个函数抛异常的困扰,方便异常排查;
  • 删除 CMS 垃圾回收器

重要特性:

  • 文本块

    示例:​image

  • ​instanceof增强

    //相当于把a赋给b
    Object a="Hello";
    if (a instanceof String b){
        System.out.println(b);
    }
    
  • record类

    image


Jdk 15

新特性:

  • EdDSA 数字签名算法
  • Sealed Classes(封闭类,预览),通过 sealed 关键字修饰抽象类限定只允许指定的子类才可以实现或继承抽象类,避免抽象类被滥用
  • Hidden Classes(隐藏类)
  • 移除 Nashorn JavaScript 引擎
  • 改进 java.net.DatagramSocket 和 java.net.MulticastSocket 底层实现

重要特性:

  • sealed类:用于显式管理类的继承

    // sealed:必须至少有一个子类,且子类必须是fina,sealed,non-sealed之一
    // permits:只准许Children、Children2继承
    public sealed class Parent permits Children, Children2 {
    }
    
    // final:该类型下不允许有子类
    public final class Children extends Parent {
    }
    
    // non-sealed:非封闭的,该类型下可以有子类
    public non-sealed class Children2 extends Parent {
    }
    
    //可以继承非封闭的类
    public class SubChildren extends Children2 {
    }
    


Jdk 16

新特性:

  • 允许在 JDK C ++源代码中使用 C ++ 14 功能
  • ZGC 性能优化,去掉 ZGC 线程堆栈处理从安全点到并发阶段
  • 增加 Unix 域套接字通道
  • 弹性元空间能力
  • 提供用于打包独立 Java 应用程序的 jpackage 工具


Jdk 17 (LTS 版本

新特性:

  • Free Java License
  • JDK 17 将取代 JDK 11 成为下一个长期支持版本
  • Spring 6 和 Spring Boot 3 需要 JDK17
  • 移除实验性的 AOT 和 JIT 编译器
  • 恢复始终执行严格模式 (Always-Strict) 的浮点定义
  • 正式引入密封类 sealed class,限制抽象类的实现
  • 统一日志异步刷新,先将日志写入缓存,然后再异步刷新

稳定版本特性汇总(相比Jdk11):

  1. 模块化
    模块化的目的,是让 jdk 的各个组件可以被分拆,复用和替换重写, 比如对 java 的 gui 不满意,可以自己实现一个 gui,对 java 的语法不满意,可以把 javac 替换成其他语言和其他语言的编译器,比如 kotlin 和 kotlinc 等,没有模块化,几乎很难实现,每次修改某个模块,总不能把整个 jdk 给重新编译一遍,再发布一个整个 sdk 吧,模块化可以帮助更有效的定制化和部署

  2. 变量类型推断

    在 Java 10 中,提供了本地变量类型推断的功能,可以通过 var 声明变量:

    var value = new MyObject();
    
  3. HTTP 客户端 API

    作为 JDK11 中正式推出的新 Http 连接器,支持的功能还是比较新的,主要的特性有:

    • 完整支持 HTTP 2.0 或者 HTTP 1.1
    • 支持 HTTPS/TLS
    • 有简单的阻塞使用方法
    • 支持异步发送,异步时间通知
    • 支持 WebSocket
    • 支持响应式流
  4. Stream API 改进

    • Collectors.teeing()​teeing 收集器已公开为静态方法 Collectors::teeing。该收集器将其输入转发给其他两个收集器,然后将它们的结果使用函数合并

      List<Student> list = Arrays.asList(
              new Student("唐一", 55),
              new Student("唐二", 60),
              new Student("唐三", 90));
      
      //平均分 总分
      String result = list.stream().collect(Collectors.teeing(
              Collectors.averagingInt(Student::getScore),
              Collectors.summingInt(Student::getScore),
              (s1, s2) -> s1 + ":" + s2));
      
      //最低分  最高分
      String result2 = list.stream().collect(Collectors.teeing(
              Collectors.minBy(Comparator.comparing(Student::getScore)),
              Collectors.maxBy(Comparator.comparing(Student::getScore)),
              (s1, s2) -> s1.orElseThrow() + ":" + s2.orElseThrow()
      ));
      
      System.out.println(result);
      System.out.println(result2);
      
    • 添加 Stream.toList 方法(jdk16)

      List<String> list = Arrays.asList("1", "2", "3");
      
      //之前这样写
      List<Integer> oneList = list.stream()
          .map(Integer::parseInt)
          .collect(Collectors.toList());
      
      //现在可以这样写
      List<Integer> twoList = list.stream()
          .map(Integer::parseInt)
          .toList();
      

  5. Switch 表达式改进

    • 支持箭头表达式(jdk12 预览 jdk14 标准)

      boolean isWeekend = switch (day) {
        case MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY -> false;
        case SATURDAY, SUNDAY -> true;
        default -> throw new IllegalStateException("Illegal day entry :: " + day);
      };
      
      
      int size = 3;
      String cn = switch (size) {
          case 1 -> "壹";
          case 2 -> "贰";
          case 3, 4 -> "叁";
          default -> "未知";
      };
      System.out.println(cn);
      
    • yield 关键字(jdk13)

      有效地从 switch 表达式返回值,并能够更容易实现策略模式

      public class SwitchTest {
          public static void main(String[] args) {
              var me = 4;
              var operation = "平方";
              var result = switch (operation) {
                  case "加倍" -> {
                      yield me * 2;
                  }
                  case "平方" -> {
                      yield me * me;
                  }
                  default -> me;
              };
              System.out.println(result);
          }
      }
      
  6. 文本块

    更容易定义长文本内容

    image

  7. 引入sealed封闭类

    用于显式管理类的继承

    // sealed:必须至少有一个子类,且子类必须是fina,sealed,non-sealed之一
    // permits:只准许Children、Children2继承
    public sealed class Parent permits Children, Children2 {
    }
    
    // final:该类型下不允许有子类
    public final class Children extends Parent {
    }
    
    // non-sealed:非封闭的,该类型下可以有子类
    public non-sealed class Children2 extends Parent {
    }
    
    //可以继承非封闭的类
    public class SubChildren extends Children2 {
    }
    
    


Jdk 18

新特性:

  • 默认字符集为 UTF-8
  • 简易的 Web 服务器
  • 优化 Java API 文档中的代码片段
  • 使用方法句柄重新实现反射核心
  • 互联网地址解析 SPI


Jdk 19

新特性:

  • 虚拟线程(预览)
  • 结构化并发(孵化)


Jdk 20

新特性:

  • 作用域值(第一次孵化)


Jdk 21

新特性:

  • ​JEP 431:序列集合
  • JEP 439:分代 ZGC
  • JEP 444:虚拟线程​
  • JEP 441:switch 模式匹配
  • JEP 444:虚拟线程

参考