【转】Java 11 特性及更新

原文链接

前言

Java 11(于2018年9月发布)包含许多重要和有用的更新。让我们看看它为开发人员和架构师带来的新特性和改进。

正文

HTTP Client API

Java长期使用HttpURLConnection类进行HTTP通信。但是随着时间的推移,需求变得越来越复杂,对应用程序的要求也越来越高。在Java 11之前,开发人员不得不求助于功能丰富的库,如Apache HttpComponentsOkHttp等。

我们看到Java 9发布版将HttpClient实现作为一个实验性特性包括在内。它随着时间的推移而发展,现在是Java 11的最后一个特性。现在,Java应用程序可以进行HTTP通信,而不需要任何外部依赖。

如何使用HttpClient

它与java.net.http模块的经典HTTP通信是类似的:

  • 创建一个HttpClient实例,并根据需要配置它。
  • 创建HttpRequest实例并填充信息。
  • 将请求传递给客户机,执行请求并检索HttpResponse的实例。
  • 处理HttpResponse中包含的信息。

HTTP API可以处理同步和异步通信。让我们来看一个简单的例子。

同步请求例子

注意,Http客户端API如何使用builder模式来创建复杂对象。

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
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());

异步请求例子

如果我们不想等待响应,可以使用异步通信。我们提供回调处理程序,它在响应可用时执行。

注意使用sendAsync()方法发送异步请求。

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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
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);
}
});
}

不用编译运行一个单文件项目

通常,对于我们想要执行的每个程序,我们都需要首先编译它为class文件。对于用于测试的小程序来说,这似乎是一个不必要的冗长过程。

Java 11做出了改变,现在我们可以执行包含在单个文件中的Java源代码,而不需要首先编译它。

HelloWorld.java

1
2
3
4
5
public class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello World!");
}
}

要执行上面的类,直接用java命令运行它。

1
2
3
$ java HelloWorld.java

Hello World!

需要注意的是,程序不能使用除java.base模块之外的任何外部依赖项,并且程序只能是单文件程序。

String API变更

String.repeat(Integer)

这个方法简单地重复一个字符串n次。它返回一个字符串,其值是重复N次的给定字符串的串联。

如果该字符串为空或count为零,则返回空字符串。

1
2
3
4
5
6
7
8
9
public class HelloWorld 
{
public static void main(String[] args)
{
String str = "1".repeat(5);

System.out.println(str); //11111
}
}

String.isBlank()

此方法判断字符串是否为空或者为空字符串。在此之前,我们一直在使用Apache开源包的StringUtils.java

1
2
3
4
5
6
7
8
9
10
11
public class HelloWorld 
{
public static void main(String[] args)
{
"1".isBlank(); //false

"".isBlank(); //true

" ".isBlank(); //true
}
}

String.strip()

此方法负责删除开头和结尾空白。我们可以更具体地使用String.stripLeading()删除开头空白,或者使用String.stripTrailing()删除结尾空白。

1
2
3
4
5
6
7
8
9
10
11
public class HelloWorld 
{
public static void main(String[] args)
{
" hi ".strip(); //"hi"

" hi ".stripLeading(); //"hi "

" hi ".stripTrailing(); //" hi"
}
}

String.lines()

这个方法有助于将多行文本处理为一个流。

1
2
3
4
5
6
7
8
9
10
11
12
13
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);
}
}

Collection.toArray(IntFunction)

在Java 11之前,将集合转换为数组并不方便。Java 11使转换更加方便。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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
}
}

Files.readString() 和 Files.writeString()

使用这些重载的方法,Java 11旨在减少大量的样板代码,使文件的读写更加容易。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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);
}
}

Optional.isEmpty()

Optional是一个容器对象,它可以包含也可以不包含一个非空值。如果没有值,则认为该对象是空的。

如果存在值,则先前存在的方法isPresent()返回true,否则返回false。有时,它迫使我们写出不方便阅读的判断语句。

isEmpty()方法与isPresent()方法相反,如果有值,则返回false,否则返回true。

所以在任何情况下我们都不需要写出相反的条件。在适当的时候使用这两种方法中的任何一种。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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 更新的内容。

相关链接: Java 11 release doc




-------------文章结束啦 ~\(≧▽≦)/~ 感谢您的阅读-------------

您的支持就是我创作的动力!

欢迎关注我的其它发布渠道