java 11_Java 11简介

本教程涵盖了Java 9到11中最重要的语言和API特性。

局部变量类型推断

Java 10引入了一个新的语言关键字var,它可以在声明局部变量时替换类型信息(本地意味着方法体内的变量声明)。

在Java 10之前,你将如下声明变量:

String text = "Hello Java 9";

现在,你可以替换String使用var。编译器从变量的赋值中推断出正确的类型。在这种情况下text是类型String:

var text = "Hello Java 10";

声明的变量var仍然是静态类型。你无法将不兼容的类型重新分配给此类变量。下面代码段无法编译:

var text = "Hello Java 11";

text = 23; // Incompatible types

你还可以结合final禁止将var变量重新分配给另一个值:

final var text = "Banana";

text = "Joe"; // Cannot assign a value to final variable 'text'

如果编译器无法推断出var正确的变量类型时,这是无法通过编译的。以下所有代码示例都会导致编译器错误:

// Cannot infer type:

var a;

var nothing = null;

var lambda = () -> System.out.println("Pity!");

var method = this::someMethod;

局部变量类型推断确实涉及泛型。在下一个示例中,current有一个相当冗长的类型Map>,可以简化为单个var关键字,从而节省你输入大量模板代码:

var myList = new ArrayList>>();

for (var current : myList) {

// current is infered to type: Map>

System.out.println(current);

}

从Java 11开始var也可以用作lambda参数,从而能为这些参数添加注释:

Predicate predicate = (@Nullable var a) -> true;

提示:在Intellij IDEA中,你可以将鼠标悬停在变量上,同时按CMD/CTRL显示变量的感应类型(按键盘爱好者按下CTRL + J)。

HTTP客户端

Java 9引入了一个HttpClient用于处理HTTP请求的新的API。从Java 11开始,这个API现在是最终完成,可以在标准库包java.net中找到。让我们来探索一下我们可以用这个API做些什么。

新的HttpClient可以同步或异步使用。同步请求会阻止当前线程,直到响应可用。BodyHandlers定义响应体的预期类型(例如,字符串,字节数组或文件):

var request = HttpRequest.newBuilder()

.uri(URI.create("https://winterbe.com"))

.GET()

.build();

var client = HttpClient.newHttpClient();

HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString());

System.out.println(response.body());

可以异步执行相同的请求。调用sendAsync不会阻塞当前线程,而是返回一个CompletableFuture构造异步操作管道。

var request = HttpRequest.newBuilder()

.uri(URI.create("https://winterbe.com"))

.build();

var client = HttpClient.newHttpClient();

client.sendAsync(request, HttpResponse.BodyHandlers.ofString())

.thenApply(HttpResponse::body)

.thenAccept(System.out::println);

我们可以省略.GET()调用,因为它是默认的请求方法。

下一个示例通过发送数据到指定的URL进行POST。类似BodyHandlers你可以用BodyPublishers来定义要作为请求主体发送的数据类型,如字符串,字节数组,文件或输入流:

var request = HttpRequest.newBuilder()

.uri(URI.create("https://postman-echo.com/post"))

.header("Content-Type", "text/plain")

.POST(HttpRequest.BodyPublishers.ofString("Hi there!"))

.build();

var client = HttpClient.newHttpClient();

var response = client.send(request, HttpResponse.BodyHandlers.ofString());

System.out.println(response.statusCode()); // 200

最后一个示例演示如何通过BASIC-AUTH以下方式执行授权

var request = HttpRequest.newBuilder()

.uri(URI.create("https://postman-echo.com/basic-auth"))

.build();

var client = HttpClient.newBuilder()

.authenticator(new Authenticator() {

@Override

protected PasswordAuthentication getPasswordAuthentication() {

return new PasswordAuthentication("postman", "password".toCharArray());

}

})

.build();

var response = client.send(request, HttpResponse.BodyHandlers.ofString());

System.out.println(response.statusCode()); // 200

集合

诸如集合List,Set并且Map已经用新方法扩展。List.of从指定的参数创建了一个新的不可变列表。List.copyOf创建列表的不可变副本。

var list = List.of("A", "B", "C");

var copy = List.copyOf(list);

System.out.println(list == copy); // true

因为list已经是不可改变的,就没有实际需要创建这种列表实例的一个副本,因此list和copy是相同的实例。但是,如果你复制一个可变列表,copy确实是一个新实例,所以它保证在改变原始列表时没有副作用:

var list = new ArrayList();

var copy = List.copyOf(list);

System.out.println(list == copy); // false

创建不可变map时,你不必自己创建map条目,而是将键和值作为参数传递:

var map = Map.of("A", 1, "B", 2);

System.out.println(map); // {B=2, A=1}

Java 11中的不可变集合仍然使用旧Collection API中的相同接口。但是,如果尝试通过添加或删除元素来修改不可变集合,则抛出java.lang.UnsupportedOperationException。

幸运的是,如果你尝试改变不可变集合,Intellij IDEA会通过检查发出警告。

Streams是在Java 8中引入的,现在有三种新方法。Stream.ofNullable是从单个元素构造流:

Stream.ofNullable(null)

.count() // 0

方法dropWhile和takeWhile都接受谓词来确定从流中放弃哪些元素:

Stream.of(1, 2, 3, 2, 1)

.dropWhile(n -> n < 3)

.collect(Collectors.toList()); // [3, 2, 1]

Stream.of(1, 2, 3, 2, 1)

.takeWhile(n -> n < 3)

.collect(Collectors.toList()); // [1, 2]

Optionals

Optionals还会有一些非常方便的新方法,例如,你现在可以简单地将Optionals转换为流,或者为空Optionals提供另一个可选的后备:

Optional.of("foo").orElseThrow(); // foo

Optional.of("foo").stream().count(); // 1

Optional.ofNullable(null)

.or(() -> Optional.of("fallback"))

.get(); // fallback

String字符串

最基本的类之一String添加一些辅助方法来修剪或检查空格以及流式传输字符串的行:

" ".isBlank(); // true

" Foo Bar ".strip(); // "Foo Bar"

" Foo Bar ".stripTrailing(); // " Foo Bar"

" Foo Bar ".stripLeading(); // "Foo Bar "

"Java".repeat(3); // "JavaJavaJava"

"A\nB\nC".lines().count(); // 3

InputStreams

最后但并非最不重要的是,InputStream最终获得了一种非常有用的方法来将数据传输到一个OutputStream,这是在处理原始数据流时非常常见的用例。

var classLoader = ClassLoader.getSystemClassLoader();

var inputStream = classLoader.getResourceAsStream("myFile.txt");

var tempFile = File.createTempFile("myFileCopy", "txt");

try (var outputStream = new FileOutputStream(tempFile)) {

inputStream.transferTo(outputStream);

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值