ThinkChat🤖让你学习和工作更高效,注册即送10W Token,即刻开启你的AI之旅 广告
# Java 11 的新特性和增强特性 > 原文: [https://howtodoinjava.com/java11/features-enhancements/](https://howtodoinjava.com/java11/features-enhancements/) Java 11(于 2018 年 9 月发布)包含许多重要且有用的更新。 让我们看看它为开发人员和建筑师带来的新特性和改进。 ## 1\. HTTP 客户端 API Java 长时间使用`HttpURLConnection`类进行 HTTP 通信。 但是随着时间的流逝,要求变得越来越复杂,对应用程序的要求也越来越高。 在 Java 11 之前,开发人员不得不诉诸特性丰富的库,例如 *Apache HttpComponents* 或 *OkHttp* 等。 我们看到 [Java 9](https://howtodoinjava.com/java9/java9-new-features-enhancements/) 版本包含`HttpClient`实现作为实验特性。 随着时间的流逝,它已经成为 Java 11 的最终特性。现在,Java 应用程序可以进行 HTTP 通信,而无需任何外部依赖。 #### 1.1 如何使用`HttpClient` 与`java.net.http`模块的典型 HTTP 交互看起来像: * 创建`HttpClient`的实例,并根据需要对其进行配置。 * 创建`HttpRequest`的实例并填充信息。 * 将请求传递给客户端,执行请求,并检索`HttpResponse`的实例。 * 处理`HttpResponse`中包含的信息。 HTTP API 可以处理同步和异步通信。 让我们来看一个简单的例子。 #### 1.2 同步请求示例 请注意,http 客户端 API 如何使用**构建器模式**创建复杂的对象。 ```java import java.io.IOException; import java.net.URI; import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; import java.time.Duration; HttpClient httpClient = HttpClient.newBuilder() .connectTimeout(Duration.ofSeconds(10)) .build(); try { String urlEndpoint = "https://postman-echo.com/get"; URI uri = URI.create(urlEndpoint + "?foo1=bar1&foo2=bar2"); HttpRequest request = HttpRequest.newBuilder() .uri(uri) .build(); HttpResponse<String> response = httpClient.send(request, HttpResponse.BodyHandlers.ofString()); } catch (IOException | InterruptedException e) { throw new RuntimeException(e); } System.out.println("Status code: " + response.statusCode()); System.out.println("Headers: " + response.headers().allValues("content-type")); System.out.println("Body: " + response.body()); ``` #### 1.2 异步请求示例 如果我们不想等待响应,那么异步通信很有用。 我们提供了回调处理程序,可在响应可用时执行。 注意使用`sendAsync()`方法发送异步请求。 ```java import java.io.IOException; import java.net.URI; import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; import java.time.Duration; import java.util.List; import java.util.concurrent.CompletableFuture; import java.util.stream.Stream; import static java.util.stream.Collectors.toList; final List<URI> uris = Stream.of( "https://www.google.com/", "https://www.github.com/", "https://www.yahoo.com/" ).map(URI::create).collect(toList()); HttpClient httpClient = HttpClient.newBuilder() .connectTimeout(Duration.ofSeconds(10)) .followRedirects(HttpClient.Redirect.ALWAYS) .build(); CompletableFuture[] futures = uris.stream() .map(uri -> verifyUri(httpClient, uri)) .toArray(CompletableFuture[]::new); CompletableFuture.allOf(futures).join(); private CompletableFuture<Void> verifyUri(HttpClient httpClient, URI uri) { HttpRequest request = HttpRequest.newBuilder() .timeout(Duration.ofSeconds(5)) .uri(uri) .build(); return httpClient.sendAsync(request,HttpResponse.BodyHandlers.ofString()) .thenApply(HttpResponse::statusCode) .thenApply(statusCode -> statusCode == 200) .exceptionally(ex -> false) .thenAccept(valid -> { if (valid) { System.out.println("[SUCCESS] Verified " + uri); } else { System.out.println("[FAILURE] Could not " + "verify " + uri); } }); } ``` ## 2\. 启动不编译的单文件程序 传统上,对于我们要执行的每个程序,我们都需要先对其进行编译。 出于测试目的,小型程序似乎不必要地耗时。 Java 11 对其进行了更改,现在我们可以执行单个文件中包含的 Java 源代码,而无需先对其进行编译。 ```java public class HelloWorld { public static void main(String[] args) { System.out.println("Hello World!"); } } ``` 要执行上述类,请直接使用`java`命令运行它。 ```java $ java HelloWorld.java Hello World! ``` > 注意,程序**不能使用`java.base module`之外的任何外部依赖项**。 并且该程序只能是**单文件程序**。 ## 3\. 字符串 API 的更改 #### 3.1 `String.repeat(int)` 此方法仅重复[字符串](https://howtodoinjava.com/java-string/)`n`次。 它返回一个字符串,其值是重复 N 次给定字符串的连接。 如果此字符串为空或`count`为零,则返回空字符串。 ```java public class HelloWorld { public static void main(String[] args) { String str = "1".repeat(5); System.out.println(str); //11111 } } ``` #### 3.2 `String.isBlank()` 此方法指示字符串是空还是仅包含空格。 以前,我们一直在 Apache 的`StringUtils.java`中使用它。 ```java public class HelloWorld { public static void main(String[] args) { "1".isBlank(); //false "".isBlank(); //true " ".isBlank(); //true } } ``` #### 3.3 `String.strip()` 此方法需要除去前导和尾随空白。 通过使用`String.stripLeading()`仅删除开头字符,或者使用`String.stripTrailing()`仅删除结尾字符,我们甚至可以更加具体。 ```java public class HelloWorld { public static void main(String[] args) { " hi ".strip(); //"hi" " hi ".stripLeading(); //"hi " " hi ".stripTrailing(); //" hi" } } ``` #### 3.4 `String.lines()` 此方法有助于将多行文本作为[**流**](https://howtodoinjava.com/java8/java-streams-by-examples/)来处理。 ```java public class HelloWorld { public static void main(String[] args) { String testString = "hello\nworld\nis\nexecuted"; List<String> lines = new ArrayList<>(); testString.lines().forEach(line -> lines.add(line)); assertEquals(List.of("hello", "world", "is", "executed"), lines); } } ``` ## 4\. `Collection.toArray(IntFunction)` 在 Java 11 之前,将集合转换为数组并不容易。 Java 11 使转换更加方便。 ```java public class HelloWorld { public static void main(String[] args) { List<String> names = new ArrayList<>(); names.add("alex"); names.add("brian"); names.add("charles"); String[] namesArr1 = names.toArray(new String[names.size()]); //Before Java 11 String[] namesArr2 = names.toArray(String[]::new); //Since Java 11 } } ``` ## 5\. `Files.readString()`和`Files.writeString()` 使用这些重载方法,Java 11 的目标是减少大量样板代码,从而使文件读写更加容易。 ```java public class HelloWorld { public static void main(String[] args) { //Read file as string URI txtFileUri = getClass().getClassLoader().getResource("helloworld.txt").toURI(); String content = Files.readString(Path.of(txtFileUri),Charset.defaultCharset()); //Write string to file Path tmpFilePath = Path.of(File.createTempFile("tempFile", ".tmp").toURI()); Path returnedFilePath = Files.writeString(tmpFilePath,"Hello World!", Charset.defaultCharset(), StandardOpenOption.WRITE); } } ``` ## 6\. `Optional.isEmpty()` [`Optional`](https://howtodoinjava.com/java8/java-8-optionals-complete-reference/)是一个容器对象,可能包含也可能不包含非`null`值。 如果不存在任何值,则该对象被认为是空的。 如果存在值,则先前存在的方法`isPresent()`返回`true`,否则返回`false`。 有时,它迫使我们编写不可读的负面条件。 `isEmpty()`方法与`isPresent()`方法相反,如果存在值,则返回`false`,否则返回`true`。 因此,在任何情况下我们都不会写负面条件。 适当时使用这两种方法中的任何一种。 ```java public class HelloWorld { public static void main(String[] args) { String currentTime = null; assertTrue(!Optional.ofNullable(currentTime).isPresent()); //It's negative condition assertTrue(Optional.ofNullable(currentTime).isEmpty()); //Write it like this currentTime = "12:00 PM"; assertFalse(!Optional.ofNullable(currentTime).isPresent()); //It's negative condition assertFalse(Optional.ofNullable(currentTime).isEmpty()); //Write it like this } } ``` 向我提供有关 Java 11 中这些**新 API 更改的问题**。 学习愉快! 参考: [Java 11 发行文档](https://docs.oracle.com/en/java/javase/11/)