Java8以后各版本新增特性

作者:Grey

原文地址:Java8以后各版本新增特性

源码

java_new_feature

Java 8

List转Map

见:List2Map.java

forEach 遍历

见:ForEachTest.java

Optional

见:OptionalTest.java

新的时间处理类

见:LocalDateTest.java

函数式接口

见:FunctionInterfaceDemo.java

Stream方法

见:StreamTest.java

数据源

  • Collection.stream (); 从集合获取流。

  • Collection.parallelStream (); 从集合获取并行流。

  • Arrays.stream (T array) or Stream.of (); 从数组获取流。

  • BufferedReader.lines (); 从输入流中获取流。

  • IntStream.of () ; 从静态方法中获取流。

  • Stream.generate (); 自己生成流

数据处理

map (mapToInt, flatMap 等)、 filter、 distinct、 sorted、 peek、 limit、 skip、 parallel、 sequential、 unordered

结果处理

forEach、 forEachOrdered、 toArray、 reduce、 collect、 min、 max、 count、 anyMatch、 allMatch、 noneMatch、 findFirst、 findAny、 iterator

代码见:StreamTest.java

惰性计算

代码见:LazyTest.java

Predicate方法

见:PredicateTest.java

Consumer方法

见:ConsumerTest.java

Supplier方法

见:SupplierTest.java

UnaryOperator方法

见:UnaryOperatorTest.java

JUC包中的CompletableFuture

见:Java多线程学习笔记

JUC包中的WorkStealingPool

见:Java多线程学习笔记

Java 9

集合创建增强

见:ImmutableListTest.java

Stream增强

见:StreamEnhanceTest.java

Iterate重载

见:IterateEnhanceTest.java

接口私有方法

见:InterfacePrivateTest.java

自带HttpClient客户端(孵化阶段)

见:HttpClientTest.java

注:jdk9中的HttpClient还在jdk.incubator.httpclient包中,jdk11已移动到java.net.http包中,可参考:(Java11新特性之HttpClient 使用_cashlifei的博客-CSDN博客)

jshell

参考:Introduction to JShell

Java 9其他更新

VarHandler

无法用单个下划线作为变量名称

1
int _ = 3; // java9 or above , error
1
String a = Objects.requireNonNullElse(m,"Bc"); // 若m不为null,则a = m,若m为null,则a = "Bc"
1
-cp, -classpath, --class-path(Java9新增)

Multi-Release JAR Files

1
2
3
4
--release
--class-path instead of -classpath
--version instead of -version
--module-path option has a shortcut -p

更多,见jeps

Java8中,接口可以有静态方法的默认实现,例:

1
2
3
4
5
6
7
8
9
public interface Test {
public static void print() {
System.out.println("interface print");
}

default void pout() {
System.out.println();
}
}

Java9中,可以支持private的静态方法实现。

1
2
3
4
5
6
7
8
9
public interface Test {
private static void print() {
System.out.println("interface print");
}

static void pout() {
print();
}
}
1
2
Optional.ofNullable(date).orElseGet(() -> newDate()); // date为null,才会执行newDate()方法,否则不执行newDate()方法
Optional.ofNullable(date).orElse(newDate()); // 无论date是否为null,都会执行newDate()方法

Java7中,可以使用try-with-Resources

1
2
3
try(Resouce res = ...) {
work with res
}

res.close()会被自动执行

例:

1
2
3
4
5
6
try (var in = new Scanner(new FileInputStream("C:\\Users\\Young\\Desktop\\新建文件夹\\1.tx.txt"), StandardCharsets.UTF_8);
var out = new PrintWriter("C:\\Users\\Young\\Desktop\\新建文件夹\\out.txt", StandardCharsets.UTF_8)) {
while (in.hasNext()) {
out.println(in.next().toUpperCase());
}
}

in 和 out执行完毕后都会自动关闭资源

在Java9 中,你可以在try中预先声明资源
例:

1
2
3
4
5
6
7
public static void printAll(String[] lines, PrintWriter out) {
try (out) { // effectively final variable
for (String line : lines) {
out.println(line);
} // out.close() called here
}
}

StackWalker用法示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
public class App {
/**
* Computes the factorial of a number
*
* @param n a non-negative integer
* @return n! = 1 * 2 * . . . * n
*/
public static int factorial(int n) {
System.out.println("factorial(" + n + "):");
var walker = StackWalker.getInstance();
walker.forEach(System.out::println);
int r;
if (n <= 1) {
r = 1;
} else {
r = n * factorial(n - 1);
}
System.out.println("return " + r);
return r;
}

public static void main(String[] args) {
try (var in = new Scanner(System.in)) {
System.out.print("Enter n: ");
int n = in.nextInt();
factorial(n);
}
}
}

Java 9 expands the use of the diamond syntax to situations where it was previously not accepted. For example , you can now use diamonds with anonymous subclasses.

1
2
3
4
5
6
ArrayList<String> list = new ArrayList<>(){
@Override
public String get(int index) {
return super.get(index).replaceAll(".","*");
}
};

Java 10

类型推断

无需定义变量类型,通过var关键字+初始化的值,可以推测出变量类型

1
2
3
4
var a = 2; // a表示int
var b = "hello"; // b 表示String
var date = new java.util.Date();
var obj = new Custome(); // 自定义对象

var 看似好用,其实也有很多限制,官方介绍了 var 只能用于下面的几种情况。

  1. 仅限带有初始化的程序的局部变量。
  2. for 循环或者增强for 循环中。
  3. for循环中的声明。

Graal

Java 9已经引入。

参数:-XX:+UnlockExperimentalVMOptions -XX:+UseJVMCICompiler

参考:官网

类数据共享

在 Java 5 中就已经引入了类数据共享机制 (Class Data Sharing,简称 CDS),允许将一组类预处理为共享归档文件,以便在运行时能够进行内存映射以减少 Java 程序的启动时间,当多个 Java 虚拟机(JVM)共享相同的归档文件时,还可以减少动态内存的占用量,同时减少多个虚拟机在同一个物理或虚拟的机器上运行时的资源占用。CDS 在当时还是 Oracle JDK 的商业特性。

Java 10 在现有的 CDS 功能基础上再次拓展,以允许应用类放置在共享存档中。CDS 特性在原来的 bootstrap 类基础之上,扩展加入了应用类的 CDS 为 (Application Class-Data Sharing,AppCDS) 支持,大大加大了 CDS 的适用范围。其原理为:在启动时记录加载类的过程,写入到文本文件中,再次启动时直接读取此启动文本并加载。设想如果应用环境没有大的变化,启动速度就会得到提升。

G1 并行全GC

早在 Java 9 时就已经引入了 G1 垃圾收集器,G1 的优点很多。而在 Java 10 中还是做了小小调整,当 G1 的并发收集线程不能快速的完成全 GC 时,就会自动切换到并行收集,这可以减少在最坏情况下的 GC 速度。

Unicode 语言标签扩展

见:UnicodeTest.java

集合API增强

见:CollectionEnhance.java

jdk10其他更新

参考:Java 10

Java 11

String API增强

如:

1
String repeated = "Java".repeat(3); // 三个Java字符串连接

更多见:StringNewAPI.java

Lambda类型推断

1
2
3
4
Map<String, Integer> map = new HashMap<>(2);
map.put("hello", 1);
map.put("world", 2);
map.forEach((var s, var i) -> System.out.println(s + " " + i));

见:LambdaInfer.java

单命令行运行Java

原先需要javac,java

1
javac Hello.java && java Hello

现在合成一个java命令搞定

1
java Hello.java

jdeprscan

JDK提供了jdeprscan 来检查你的代码是否使用了deprecated的方法

更多Java 11特性

Java 11 新特性介绍

Java 12

新版Switch使用方式

jdk12中是预览特性,在jdk14正式引入

见:NewSwitch.java

文件对比

见:FileMisMatchTest.java

简化数字格式显示

见:CompactNum.java

更多jdk12特性

jdk12新特性

Java 13

Switch 增强(预览功能)

增加yield表示返回值, 在jdk13是实验性功能,到jdk14可以正式使用

见:SwitchYield.java

文本块(预览功能)

jdk13属于预览功能,在jdk15中正式启用

见:BlockTest.java

Java 13更多新特性

Java 13 新功能介绍

Java 14

instanceof 判断(预览功能)

见:InstanceofInJdk14.java

NullPointerException提示信息优化

如下代码:

1
2
3
4
5
6
public class NullPointerTest {
public static void main(String[] args) {
String s = null;
System.out.println(s.isBlank());
}
}

报错信息如下:

1
2
Exception in thread "main" java.lang.NullPointerException: Cannot invoke "String.isBlank()" because "s" is null
at git.snippets.jdk14.NullPointerTest.main(NullPointerTest.java:14)

会提示出具体哪个对象是null

1
... because "s" is null

Switch 增强 (正式)

Java 12和Java 13 都是预览版,到了Java14,成为正式版

见:SwitchInJdk14.java

Records(预览功能)

见:RecordsTest.java

到jdk16正式发布

文本块(二次预览功能)

参考jdk13的文本块内容

增加了

\结尾不换行

\s表示一个空格

见:BlockInJdk14.java

在jdk15中正式启用

Java14中更多特性

Java 14 新功能介绍

Java 15

文本块正式启用

见:BlockTestInJava15.java

Sealed Classes (预览,到java17中正式启用)

被 sealed 修饰的类可以指定子类。这样这个类就只能被指定的类继承。

见:SealedClassTest.java

移除 Nashorn JavaScript 引擎

Nashorn JavaScript 引擎在 Java 8 中被引入,在 Java 11 中被标记为废弃。由于 ECMAScript 语言发展很快,维护 Nashorn JavaScript 的成本过于高昂,在 Java 15 中被彻底删除。

instanceof 类型匹配 (二次预览)

见 Java 14中的instanceof 类型匹配

Records(二次预览)

见:Java 14中的Records功能

Java 15中更多的功能

Java 15 新功能介绍

Java 16

Sealed Classes 预览

参考:Java15中提到的Sealed Classes

打包工具

在 Java 14 中是预览功能,到Java 16中正式启用

使用 jpackage 命令可以把 JAR 包打包成不同操作系统支持的软件格式。

1
jpackage --name myapp --input lib --main-jar main.jar --main-class myapp.Main

常见平台格式如下:

Linux: deb and rpm
macOS: pkg and dmg
Windows: msi and exe

要注意的是,jpackage 不支持交叉编译,也就是说在 windows 平台上是不能打包成 macOS 或者 Linux 系统的软件格式的。

instanceof 模式匹配

在jdk14中开始作为预览功能,jdk16正式启用

见:InstanceofInJdk16.java

Records

在Java15开始作为预览功能,jdk16正式启用

见:RecordsInJava15.java

Java16更多特性

Java 16 新功能介绍

Java 17

Sealed Classes 正式启用

见:SealedClassInJdk17.java

Switch类型匹配(预览功能)

见:SwitchMatchTest.java

更多Java17新功能

Java17新特性

参考资料

Spring in Action, 5th

Java核心技术·卷 I(原书第11版)

Java核心技术·卷 II(原书第11版)

Java 新特性教程

再见Java8!万字总结Java 9~15新特性!真香