Java 12 新特性

JDK12-15新特性 - 图1

1. Switch 表达式扩展(预览功能)

传统的switch语句,容易漏写break而出错,同时写法并不简洁优雅。
Java 12之前

  1. switch (day) {
  2. case MONDAY:
  3. case FRIDAY:
  4. case SUNDAY:
  5. System.out.println(6);
  6. break;
  7. case TUESDAY:
  8. System.out.println(7);
  9. break;
  10. case THURSDAY:
  11. case SATURDAY:
  12. System.out.println(8);
  13. break;
  14. case WEDNESDAY:
  15. System.out.println(9);
  16. break;
  17. }

JDk 12 之后,Switch表达式得到增强,能接受语句和表达式。

switch (day) {
    case MONDAY, FRIDAY, SUNDAY -> System.out.println(6);
    case TUESDAY                -> System.out.println(7);
    case THURSDAY, SATURDAY     -> System.out.println(8);
    case WEDNESDAY              -> System.out.println(9);
}

2. 紧凑的数据格式

JDK 12 新增了NumberFormat对复杂数字的格式化

NumberFormat numberFormat = NumberFormat.getCompactNumberInstance(Locale.CHINA, NumberFormat.Style.SHORT);
System.out.println(numberFormat.format(100000));
//output
10万

3. 字符串支持transform、indent操作

  • transform 字符串转换,可以配合函数式接口Function一起使用

    List<String> list1 = List.of("语雀", " 原子");
    List<String> list2 = new ArrayList<>();
    list1.forEach(element ->
              list2.add(element.transform(String::strip)
                      .transform((e) -> "Hello," + e))
      );
    list2.forEach(System.out::println);
    //输出
    Hello,语雀
    Hello,原子
    
  • indent 缩进,每行开头增加空格space和移除空格

    String result = "Java\n Python\nC".indent(3);
    System.out.println(result);
    //输出
     Java
      Python
     C
    

    4. Files.mismatch(Path, Path)

    Java 12 新增了mismatch方法,此方法返回第一个不匹配的位置,如果没有不匹配,则返回 -1L。

    public static long mismatch(Path path, Path path2) throws IOException;
    

    代码示例:

    Path file1 = Paths.get("c:\\jay.txt");
    Path file2 = Paths.get("c:\\语雀.txt");
    try {
    long fileMismatch = Files.mismatch(file1, file2);
    System.out.println(fileMismatch);
    } catch (IOException e) {
      e.printStackTrace();
    }
    

    5. Teeing Collector

    Teeing Collector 是 Streams API 中引入的新的收集器实用程序,它的作用是 merge 两个 collector 的结果,API格式如下:

    public static <T, R1, R2, R>
      Collector<T, ?, R> teeing(Collector<? super T, ?, R1> downstream1,
      Collector<? super T, ?, R2> downstream2,
      BiFunction<? super R1, ? super R2, R> merger)
    

直接看代码例子吧,如下为求学生的平均分和总分的例子

List<Student> studentList= Arrays.asList(
                new Student("jay", 90),
                new Student("捡田螺的小男孩", 100),
                new Student("捡表情的小男孩", 80)
        );
        String teeingResult=studentList.stream().collect(
                Collectors.teeing(
                        Collectors.averagingInt(Student::getScore),
                        Collectors.summingInt(Student::getScore),
                        (s1,s2)-> s1+ ":"+ s2
                )
        );
 System.out.println(teeingResult); //90:270

6.其他特性

  • 支持unicode 11(684个新字符、11个新blocks、7个新脚本)
  • JVM 常量 API (主要在新的java.lang.invoke.constant包中定义了一系列基于值的符号引用类型,能够描述每种可加载常量。)
  • Shenandoah GC(低暂停时间垃圾收集器)
  • G1 收集器提升 (可中止的混合收集集合、及时返回未使用的已分配内存)
  • 默认CDS档案
  • JMH 基准测试

Java 13 新特性

JDK12-15新特性 - 图2

1.Switch 表达式扩展(引入 yield 关键字)

传统的switch:

private static String getText(int number) {
    String result = "";
    switch (number) {
        case 1, 2:
        result = "one or two";
        break;
        case 3:
        result = "three";
        break;
        case 4, 5, 6:
        result = "four or five or six";
        break;
        default:
        result = "unknown";
        break;
复制代码

Java 13之后,value break 语句不再被编译,而是用 yield 来进行值返回

private static String getText(int number) {
    return switch (number) {
        case 1, 2:
            yield "one or two";
        case 3:
            yield "three";
        case 4, 5, 6:
            yield "four or five or six";
        default:
            yield "unknown";
    };
}


2.文本块升级

Java 13之前,字符串不能够多行使用,需要通过换行转义或者换行连接符等等,反正就是好麻烦、好难维护。

String html = "<html>\n" +
              "    <body>\n" +
              "        <p>Hello, 语雀原子</p>\n" +
              "    </body>\n" +
              "</html>\n";

Java 13之后,清爽多了~

String html = """
                <html>
                    <body>
                        <p>Hello,  语雀原子</p>
                    </body>
                </html>
                """;

3. SocketAPI 重构

  • 传统的Java Socket API(java.net.ServerSocket 和 java.net.Socket)依赖于SocketImpl 的内部实现
  • 在 Java 13之前,通过使用 PlainSocketImpl 作为 SocketImpl 的具体实现。
  • Java 13 中的新底层实现,引入 NioSocketImpl 的实现用以替换 SocketImpl 的 PlainSocketImpl 实现,此实现与 NIO(新 I/O)实现共享相同的内部基础结构,并且与现有的缓冲区高速缓存机制集成在一起。

一个Socket简单例子:

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
public class SocketAPITest {
    public static void main(String[] args) {
        try (ServerSocket serverSocket = new ServerSocket(8080)){
            boolean runFlag = true;
            while(runFlag){
                Socket clientSocket = serverSocket.accept();
                //搞事情
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

运行以上的实例,看下是否有以下关键词输出~

[class,load] sun.nio.ch.NioSocketImpl

4.FileSystems.newFileSystem新方法

FileSystems 类中添加了以下三种新方法,以便更容易地使用将文件内容视为文件系统的文件系统提供程序:

  • 1、newFileSystem(Path)
  • 2、newFileSystem(Path, Map)
  • 3、newFileSystem(Path, Map, ClassLoader)


5. 增强 ZGC 释放未使用内存

  • ZGC 是Java 11 中引入的最为瞩目的垃圾回收特性,是一种可伸缩、低延迟的垃圾收集器。但是实际使用中,它不能够主动将未使用的内存释放给操作系统。
  • Java 13 中对 ZGC 的改进,包括释放未使用内存给操作系统、支持最大堆大小为 16TB、JVM参数-XX:SoftMaxHeapSize 来软限制堆大小

6.其他特性

  • 动态 CDS 存档, 扩展了 Java 10 中引入的类数据共享功能, 使用CDS 存档变得更容易。
  • 文本块的字符串类新方法,如formatted(Object…args),stripIndent()等。

Java 14 新特性

JDK12-15新特性 - 图3

1. instanceof模式匹配

instanceof 传统使用方式:

if (person instanceof Singer) {
    Singer singer = (Singer) person;
    singer.sing();
} else if (person instanceof Writer) {
    Writer writer = (Writer) person;
    writer.write();
}

Java 14 对 instanceof 进行模式匹配改进之后

if (person instanceof Singer singer) {
    singer.sing();
} else if (person instanceof Writer writer) {
   writer.write();
}

2.Record 类型(预览功能)

Java 14将Record 类型作为预览特性而引入,有点类似于Lombok 的@Data注解,看个例子吧:

public record Person(String name, int age) {
    public static String address;
    public String getName() {
        return name;
    }
}

反编译结果:

public final class Person extends java.lang.Record {
    private final java.lang.String name;
    private final java.lang.String age;
    public Person(java.lang.String name, java.lang.String age) { /* compiled code */ }
    public java.lang.String getName() { /* compiled code */ }
    public java.lang.String toString() { /* compiled code */ }
    public final int hashCode() { /* compiled code */ }
    public final boolean equals(java.lang.Object o) { /* compiled code */ }
    public java.lang.String name() { /* compiled code */ }
    public java.lang.String age() { /* compiled code */ }
}

可以发现,当用 Record 来声明一个类时,该类将自动拥有下面特征:

  • 构造方法
  • hashCode() 方法
  • euqals() 方法
  • toString() 方法
  • 类对象被final 关键字修饰,不能被继承。


    3. Switch 表达式-标准化

    switch 表达式在之前的 Java 12 和 Java 13 中都是处于预览阶段,终于在 Java 14 标准化,成为稳定版本。

  • Java 12 为switch 表达式引入Lambda 语法

  • Java 13 使用yield代替 break 关键字来返回表达式的返回值。
    String result = switch (day) {
      case "M", "W", "F" -> "MWF";
      case "T", "TH", "S" -> "TTS";
      default -> {
          if (day.isEmpty()) {
              yield "Please insert a valid day.";
          } else {
              yield "Looks like a Sunday.";
          }
      }
    };
    System.out.println(result);
    

    4. 改进 NullPointerExceptions提示信息

    Java 14 之前: ```java String name = song.getSinger().getSingerName()

//堆栈信息 Exception in thread “main” java.lang.NullPointerException at NullPointerExample.main(NullPointerTest.java:6)


Java 14,通过引入JVM 参数`-XX:+ShowCodeDetailsInExceptionMessages`,<br />可以在空指针异常中获取更为详细的调用信息。

Exception in thread “main” java.lang.NullPointerException: Cannot invoke “Singer.getSingerName()” because the return value of “rainRow.getSinger()” is null at NullPointerExample.main(NullPointerTest.java:6) 复制代码

<a name="abf66162"></a>
#### 
<a name="2Cn2A"></a>
#### 5. 其他特性

- G1 的 NUMA 可识别内存分配
- 删除 CMS 垃圾回收器
- GC 支持 MacOS 和 Windows 系统

---

<a name="X7ZnI"></a>
### Java 15 新特性

![](https://cdn.nlark.com/yuque/0/2020/png/153889/1605371983786-0be3d3bd-efb5-4713-acfa-6a2682533b78.png#align=left&display=inline&height=489&margin=%5Bobject%20Object%5D&originHeight=489&originWidth=1334&size=0&status=done&style=none&width=1334)

<a name="wOEcs"></a>
#### 1.EdDSA 数字签名算法

- 使用 Edwards-Curve 数字签名算法(EdDSA)实现加密签名。
- 与其它签名方案相比,EdDSA 具有更高的安全性和性能。
- 得到许多其它加密库(如 OpenSSL、BoringSSL)的支持。
<a name="Qs4VT"></a>
#### <br />
<a name="zvXRZ"></a>
#### 2.Sealed Classes(封闭类,预览)
封闭类,可以是封闭类、封闭接口,防止其他类或接口扩展或实现它们。
```java
public abstract sealed class Singer
    permits Jay, Eason{
    ...
}

类Singer被sealed 修饰,是封闭类,只能被2个指定子类(Jay, Eason)继承。

3. Hidden Classes(隐藏类)

  • 隐藏类天生为框架设计的。
  • 隐藏类只能通过反射访问,不能直接被其他类的字节码。

    4. Remove the Nashorn JavaScript Engine

  • Nashorn太难维护了,移除 Nashorn JavaScript引擎成为一种必然

  • 其实早在JDK 11 中就已经被标记为 deprecated 了。

5.Reimplement the Legacy DatagramSocket API(重新实现DatagramSocket API)

  • 重新实现老的DatagramSocket API
  • 更改java.net.DatagramSocket 和 java.net.MulticastSocket 为更加简单、现代化的底层实现。


    6.其他

  • Disable and Deprecate Biased Locking(准备禁用偏向锁)

  • instanceof 自动匹配模式(预览)
  • ZGC,一个可伸缩、低延迟的垃圾回收器。(转正)
  • Text Blocks,文本功能转正(JDK 13和14预览,14终于转正)
  • Remove the Solaris and SPARC Ports(删除 Solaris 和 SPARC 端口)
  • 外部存储器访问 API(允许Java 应用程序安全有效地访问 Java 堆之外的外部内存。)
  • Record类型二次预览(在Java 14就预览过啦)