Java SE 11 新增特性
阅读原文时间:2023年07月08日阅读:3

Java SE 11 新增特性

作者:Grey

原文地址:Java SE 11 新增特性

源仓库: Github:java_new_features

镜像仓库: GitCode:java_new_features

JDK 10引入了局部变量类型推理(JEP 286)。这简化了代码,因为你不再需要明确说明局部变量的类型,而是可以使用varJEP 323将这种语法的使用扩展到Lambda表达式的参数。这里有一个简单的例子。

package git.snippets.jdk11;

import java.util.HashMap;
import java.util.Map;

/**
 * lambda类型推断
 *
 * @author <a href="mailto:410486047@qq.com">Grey</a>
 * @date 2021/11/29
 * @since 11
 */
public class LambdaInfer {
    public static void main(String[] args) {
        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));
    }
}

原先需要javac,然后java

javac Hello.java && java Hello

现在合成一个java命令搞定

java Hello.java

同样的

java -classpath /home/foo/java Hello.java Bonjour

等同于如下两条

javac -classpath /home/foo/java Hello.java

java -classpath /home/foo/java Hello Bonjour

该JEP还提供“shebang”支持。为了减少在命令行上提及Java启动器的需要,包含在源文件的第一行。例如:

# !/usr/bin/java --source 11

   public class HelloWorld {
   ...
   }

注:--source 11是必要的,指定了JDK的版本。

JDK 9 引入了一个新的 API 来提供支持 HTTP 客户端协议,该API被作为孵化器模块包含在内。孵化器模块旨在提供新的 API,而不会使它们成为Java SE标准的一部分。开发人员可以试用 API 并提供反馈。

HTTP Client API 现在是Java SE 11标准的一部分。JDK 引入了一个新的模块和包:java.net.http。该 API 可以同步或异步使用。

示例代码如下

package git.snippets.jdk11;

import java.io.IOException;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;

/**
 * jdk9 中httpclient还在jdk.incubator.httpclient模块中
 *
 * @author <a href="mailto:410486047@qq.com">Grey</a>
 * @date 2021/11/29
 * @since 11
 */
public class HttpClientTest {
    public static void main(String[] args) throws IOException, InterruptedException {
        HttpClient client = HttpClient.newHttpClient();
        URI uri = URI.create("http://httpbin.org/get");
        HttpRequest req = HttpRequest.newBuilder(uri).header("accept", "application/json").GET().build();
        HttpResponse<String> resp = client.send(req, HttpResponse.BodyHandlers.ofString());
        String body = resp.body();
        System.out.println(body);
    }
}

执行后控制台输出

{
  "args": {},
  "headers": {
    "Accept": "application/json",
    "Content-Length": "0",
    "Host": "httpbin.org",
    "Http2-Settings": "AAEAAEAAAAIAAAABAAMAAABkAAQBAAAAAAUAAEAA",
    "Upgrade": "h2c",
    "User-Agent": "Java-http-client/18.0.1",
    "X-Amzn-Trace-Id": "Root=1-62fddb2a-7813af3246da12d203c31825"
  },
  "origin": "211.136.194.3",
  "url": "http://httpbin.org/get"
}

随着 JDK 9 中 JPMS 的引入,可以将整体式 rt.jar 文件划分为多个模块。JPMS 的另一个优点是,现在可以创建一个仅包含应用程序所需模块的 Java 运行时,从而大大减小了依赖包的大小。通过明确定义的模块边界,现在可以更轻松地删除 Java API 中过时的部分。

java.se.ee元模块包括六个模块,这些模块将不再是 Java SE 11 标准的一部分,也不再包含在 JDK 中。受影响的模块包括:

  • corba

  • transaction

  • activation

  • xml.bind

  • xml.ws

  • xml.ws.annotation

自 JDK 9 以来,这些模块已被弃用,并且默认情况下未包含在编译或运行时中。如果您尝试编译或运行一个应用程序,该应用程序在 JDK 9 或 JDK 10 上使用这些模块中的 API 的时候会报错。如果在代码中使用这些模块中的 API,则需要将它们作为单独的模块或库提供。

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

举几个例子,String类中增加了很多有用的 API。

package git.snippets.jdk11;

/**
 * String 新增API
 *
 * @author <a href="mailto:410486047@qq.com">Grey</a>
 * @date 2021/11/29
 * @see String
 * @since 11
 */
public class StringNewAPI {
    public static void main(String[] args) {
        isBlankTest();
        linesTest();
        repeatTest();
        stripTest();
    }
    // 按行打印
    private static void linesTest() {
        String abcd = "\na\nb\tc\td";
        abcd.lines().forEach(System.out::println);
    }
    // String.isBlank()
    private static void isBlankTest() {
        String blank = "   ";
        System.out.println(blank.isBlank());
    }

    static void repeatTest() {
        String repeat = "abcd";
        // repeat(n) 表示复制几次
        String repeat3 = repeat.repeat(3);
        System.out.println(repeat3);
    }

    //trim 只能去除半角空格,而 strip 是去除各种空白符。
    static void stripTest() {
        String a = "   bbbd a  ";
        String b = a.strip();
        System.out.println(b);
        System.out.println(a);
        String strip = "    我是       ";
        // 去前面空白字符,如全角空格,TAB
        System.out.println("==" + strip.stripLeading() + "==");
// 去后面空白字符,如全角空格,TAB
        System.out.println("==" + strip.stripTrailing() + "==");
    }
}

File中增加了一些 API,比如Files.writeStringFiles.readString

package git.snippets.jdk11;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;

/**
 * File增强API
 *
 * @author <a href="mailto:410486047@qq.com">Grey</a>
 * @date 2021/11/29
 * @since
 */
public class FileNewAPI {
    public static void main(String[] args) throws IOException {
        testFile();
    }

    static void testFile() throws IOException {
        // 创建临时文件
        Path path = Files.writeString(Files.createTempFile("test", ".txt"), "hello world,你好,世界");
        System.out.println(path);
// 读取文件
// String ss = Files.readString(Path.of("file.json"));
        String s = Files.readString(path);
        System.out.println(s);
    }
}

OptionalPredicate相关 API 增强

package git.snippets.jdk11;

import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.function.Predicate;
import java.util.stream.Collectors;

/**
 * Optional用法
 *
 * @author <a href="mailto:410486047@qq.com">Grey</a>
 * @date 2021/11/19
 * @since 11
 */
public class OptionalAndPredicateTest {
    public static void main(String[] args) {
        Optional<String> helloOptional = Optional.of("Hello");
        Optional<String> emptyOptional = Optional.empty();
        helloOptional.ifPresent(s -> System.out.println(s.length()));
        emptyOptional.ifPresent(s -> System.out.println(s.length()));
        List<String> lines = Arrays.asList("a", "  ", "", null, "b");
        List<String> ans = lines.stream().filter(Objects::nonNull).filter(Predicate.not(String::isBlank)).collect(Collectors.toList());
        System.out.println(ans);
    }
}

JDK 10 到 JDK 11 所有涉及调整的API清单见:JDK 10.0.2 to 11+28 API Change Report

Java SE 7及以后各版本新增特性

Java Language Updates

JDK 11 Release Notes

90 New Features and APIs in JDK 11 (Part 1)

90 New Features and APIs in JDK 11 (Part 2)

JDK 10.0.2 to 11+28 API Change Report