Java教程

聊聊Java9-17带来了什么新特性

本文主要是介绍聊聊Java9-17带来了什么新特性,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

Java8 引入 Lambda 表达式和流以后,带来了函数式编程风格。往后的Java 版本发布节奏加快,切换每六个月一个新版本,很多新特性可能不少人都不清楚。尽管如今大部分场景都是Java 8,但了解行业变化也是每个 Java 程序员需要的。本文主要介绍 Java 9 到 17的新增的一些语言特性,涉及一些底层实现的变化会简单列举。

目录

Java9

  • 模块化
  • 接口支持私有方法
  • 改进 try-with-resources 语法
  • 增强流(Stream)API
  • REPL——JShell
  • 多Jdk版本共存 jar

Java10

  • 局部类型推断

Java11

  • String API 增强
  • 局部类型推断增强
  • HTTP Client 增强

Java12

  • switch表达式语法糖

Java13

  • 文本块

Java14

  • instanceof 类型判断
  • 打包工具
  • NullPointerException优化提示
  • Record类

Java15

  • 隐藏类
  • 密封类
  • 禁用和废除偏向锁
  • ZGC正式发布

Java16
Java17

  • 恢复严格的浮点语义
  • 删除Applet
  • switch类型匹配

Java 9

Java9 是Java8后一个比较大的更新,包含新特性比较多

模块化

module 是新增的Java代码访问权限级别,每个module可以包含多个package。
通过module-info.java文件来声明该文件夹及其子文件夹为一个模块,exports 关键字可以用来控制模块内哪些包对外暴露。

 module store.api{
   exports com.dingtalk.store.api;
 }

使用module后,即使包中的类是public的,如果未通过exports显式导出其程序包,则外部模块是不可调用的。
如果一个模块想要使用被另一个模块导出的package包中的类,可以用requires关键字在其module-info.java文件中来导入(读取)目标模块的package包。

 module store.service {
   requires com.dingtalk.store.api;
 }

Java9 module 和 Maven module 很像,但功能完全不一样,后者是作为依赖构建来方便管理应用代码,而Java Module是在于安全性、访问性控制,通过exports/requires 控制模块内需要暴露和依赖的具体包。

接口支持定义私有方法

interface DemoI {
	private void privateMethod() {
		System.out.println("private");
	}
}

改进try-with-resources语法

try-with-resources 语法的 try() 可以包含变量,多个变量用分号隔开。
改进后让语义更加清晰,将资源创建和资源回收的语法拆分。

public void testTryWithResources(String fileName) {
    FileOutputStream fos = new FileOutputStream(fileName);
    OutputStreamWriter osw = new OutputStreamWriter(fos);
    BufferedWriter bw = new BufferedWriter(osw);
    
    try (bw;osw;fos) {
    	bw.write("something");
    	bw.flush();
	}
	/*
	  对比Java7:
	  try(FileOutputStream fos = new FileOutputStream(fileName);
      	  OutputStreamWriter osw = new OutputStreamWriter(fos);
      	  BufferedWriter bw = new BufferedWriter(osw);){
	      bw.write("something");
	      bw.flush();
	  }
	 */
}

增强流(Stream)API

1、Stream.takeWhile(Predicate):处理流中的数据直到条件 predicate 返回 false 则终止执行。

public void test() {
	Stream.of(1, 2, 3, 4, 5)
		.takeWhile(i -> i != 3)
		.forEach(System.out::println);
	/*
	  输出结果:
	  1
	  2
	 */
}

2、Stream.dropWhile(Predicate):与 taskWhile 相反,直到条件 predicate 返回 false 才开始处理其后面流中的数据。

public void test() {
	Stream.of(1, 2, 3, 4, 5)
		.dropWhile(i -> i != 3)
		.forEach(System.out::println);
	/*
	  输出结果:
	  4
	  5
	 */
}

3、Stream.iterate: 会循环遍历流中的数据,直到条件返回 false 时停止
方法定义如下:

/**
  * @param seed 初始化循环变量
  * @param hasNext 循环条件
  * @param next 下一次循环值
  **/
static <T> Stream<T> iterate(T seed, Predicate<? super T> hasNext, UnaryOperator<T> next)

示例:

public void test() {
	IntStream.iterate(1, x -> x < 10, x -> x + 5).forEach(System.out::println);
	/*
	  输出结果:
	  1
	  6
	 */
}

4、Stream.ofNullable:对Stream.of的扩展,创建流时对空入参返回空Stream

REPL——JShell

REPL,全称 Read Eval Print Loop ,「 交互式解释器 」,一种支持代码所见即所得的即时编译器。
一些简单代码逻辑可以直接通过 Jshell 执行,不需要同故宫 javac 编译了。

多Jdk版本共存jar

在同一个Jar包可以包含多个Java版本的class文件,在不同Jdk环境下使用对应该 jdk 版本的 jar。
(这对算是用户很友好的功能)

Java 10

局部类型推断

新增关键字var 使得 Java 可以像 js 一样,自动推断数据类型。仅限于局部变量,算是一个语法糖,底层还没有变,在编译期推断出变量的实际类型。

var str = "show the var";

其他关于底层的优化不展开了,直接列举

  • 用于 G1 的并行 Full GC
  • 类数据共享
  • 基于 Java 的 JIT 编译器(实验性)

Java 11

继 Java8 后的又一个 LTS (long-term support)版本,自 Java 11 起,Oracle JDK 将不再免费提供商业用途。

StringAPI增强

1、String.isBlank():去前后空白字符的字符串判空
2、lines():按行分割字符串,得到一个字符串流
3、repeat():复制字符串
4、strip():去除前后空白字符(区别于 trim() 只能去除半角空格)

局部类型推断增强

允许在lambda表达式中使用 var

list.stream()
  .map((@NotNull var x) -> x.toUpperCase()));

HTTPClient增强

在 Java 11 中 Http Client API 得到了标准化的支持。且支持 HTTP/1.1 和 HTTP/2 ,也支持 websockets。

HttpRequest request = HttpRequest.newBuilder()
        .uri(URI.create("https://www.dingtalk.com"))
        .build();
HttpClient client = HttpClient.newHttpClient();
// 异步
client.sendAsync(request, HttpResponse.BodyHandlers.ofString())
        .thenApply(HttpResponse::body)
        .thenAccept(System.out::println)
        .join();

// 同步
HttpResponse<String> response = client.send(request, 
	HttpResponse.BodyHandlers.ofString());

关于底层的优化

  • 可扩展的低延迟垃圾收集器 ZGC(虽然是实验阶段,但能算是 Java11 最重要的特性)
  • 基于嵌套的访问控制

Java 12

switch表达式语法糖

原先 switch 总需要使用 break 来做到每个 case 间隔离,Java 12 后通过 case L -> 来实现。并且支持了返回值,可进行赋值。

String season = switch (day) {
    case "march", "april", "may"            -> "春天";
    case "june", "july", "august"           -> "夏天";
    case "september", "october", "november" -> "秋天";
    case "december", "january", "february"  -> "冬天";
    default -> {
        break "unknown";
    }
};

Java 13

文本块

文本块目前还是预览功能,方便创建多行字符串
以往在代码中声明一个长长的字符串常量,通过需要换行使用 + 连接。

String html ="<html>\n" +
			  "   <body>\n" +
			  "      <p>Hello, World</p>\n" +
			  "   </body>\n" +
			  "</html>\n";

采用文本块的方式,示例:

String html =  """
               <html>
                   <body>
                       <p>Hello, World</p>
                   </body>
               </html>
				        """;

Java 14

instanceof类型判断

目前还是预览功能,作用是在使用 instanceof 判断是所属类型后,自动类型转换。

// java14之前
if (obj instanceof String) {
	String str = (String) obj;
	...
}

// java14之后
if (obj instanceof String str) {
	...
}

打包工具

Java 14 引入了打包工具,命令是 jpackage,使用 jpackage 命令可以把 JAR 包打包成不同操作系统支持的软件格式。

主要的几个平台格式如下:

  • Linux: debrpm
  • macOS: pkgdmg
  • Windows: msiexe

NullPointerException优化提示

原先的空指针异常只能直到是第几行报错,无法确定这一行中具体哪个字段。Java 14 中的空指针会清晰地提示出具体字段。

Exception in thread "main" java.lang.NullPointerException: 
	Cannot invoke "String.length()" because "test" is null

Record类

Record 是新的类型,和枚举类似的受限形式,本质上是一个 final 类。

// 定义
public record Person(String name, String gender) {
}

// 使用
Person tom = new Person("Tom", "male");
Person june = new Person("June", "female");

Java 15

隐藏类

这个可以让开发者引入无法被其他地方发现使用,且生命周期有限的类。这对于运行时动态生成类(反射)的使用方式十分有利,可以减少内存占用,应该比较适合框架开发中使用。

密封类

Java15中还是预览特性。密封类用来控制允许继承它的子类,不是随便子类想继承就能继承

public sealed interface Animal permits Dog, Cat {
    //...
}

禁用和废除偏向锁

synchronized 同步时的锁膨胀机制中有一个就是偏向锁,这个的引入增加了JVM的复杂度,但是对性能提升程度一般,于是默认禁用了。

ZGC正式发布

ZGC 作为可扩展低延迟垃圾收集器,在Java11引入后,Java15正式投入使用了。

Java 16

Java 16 在语法上的新特性更新比较多,主要是一些之前版本引入的预览特性正式发布。比如Java14中的打包工具、instanceof、Record类

Java 17

Java 17 在 2021 年 9 月 14 日正式发布,Java 17 是一个 LTS 版本。

恢复严格的浮点语义

Java 1.2 在中引入了Java对默认浮点语义的更改,牺牲一点浮点精度来提高JVM性能,并引入了strictfp来手动启用严格浮点语义。Java17恢复了严格浮点语义作为默认语义。

删除Applet

Applet 是使用 Java 编写的可以嵌入到 HTML 中的小应用程序,嵌入方式是通过普通的 HTML 标记语法,由于早已过时,几乎没有场景在使用了,在Java17中彻底删除。

switch类型匹配

预览特性。和instanceof一样,switch 增加了类型匹配自动转换功能

static String test(Object o) {
    return switch (o) {
        case Integer i -> String.format("int %d", i);
        case Long l    -> String.format("long %d", l);
        case Double d  -> String.format("double %f", d);
        case String s  -> String.format("String %s", s);
        default        -> o.toString();
    };
}

其他一些特性简单列举如下:

  • 增强伪随机数生成器
  • 密封类正式发布

总结

可以看到Java快速迭代的版本参考了其他语言、类库的语法设计,带来不少语法糖。随着每 6 个月一次的快速发布周期,更多的变化被引入,保持关注 Java 平台的变化就更加重要了。目前 Java 中的 Lambda 对于函数式的支持还比较单薄,期待后续更新能有这方面的增强。

这篇关于聊聊Java9-17带来了什么新特性的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!