资讯专栏INFORMATION COLUMN

Java 11 教程

douzifly / 705人阅读

摘要:原文链接已于成功发布,不过目前绝大多数人在生产环境仍旧使用的是。这篇以案例为主的教程涵盖了从到的绝大多数重要的语法与特性。当编译器不能正确识别出变量的数值类型时,将不被允许使用。同步请求将会阻塞当前的线程,直到返回响应消息。

原文链接:https://wangwei.one/posts/921...

Java11 已于 2018/09/25 成功发布,不过目前 绝大多数人 在生产环境仍旧使用的是Java 8。这篇以案例为主的教程涵盖了从 Java 9 到 Java 11的绝大多数重要的语法与API特性。让我们开始吧!

局部变量类型推断

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

Java 10之前,变量的声明形式如下:

String text = "Hello Java 9";

现在,你可以使用 var 替换 String 。编译器将会从变量的赋值中推断出它的正确类型。在这个例子里 变量text 即为 String 类型:

var text = "Hello Java 10";

不同于 Javascript 中的 var 关键字,Java中的 var 声明的变量仍旧是静态类型。你不能再次赋予另一个与原类型不符的变量值。

var text = "Hello Java 11";
text = 23;  // ERROR: Incompatible types(类型错误)

var 关键字还可以与 final 一起使用,意义同之前的版本一样,表示不可修改。

final var text = "Hello Java 10";
text = "Hello Java 11"; // 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开始,lambda表达式的参数也允许使用var关键字,这样使得你可以为这些参数添加注解标识:

Predicate predicate = (@Nullable var a) -> true;
Tip:在Intellij IDEA中,你可以在按住CMD / CTRL的同时将鼠标悬停在变量上,以显示变量的推断类型。
HTTP Client

Java 9引入了一个新的孵化HttpClient API来处理HTTP请求。从Java 11开始,这个API已经可以在标准库 java.net 中使用了。让我们来探索一下通过这个API我们可以做些什么。

这个新的 HttpClient 既可以被同步使用,也可以被异步使用。同步请求将会阻塞当前的线程,直到返回响应消息。BodyHandlers 定义了响应消息体的类型(e.g string,byte-array 或 file):

var request = HttpRequest.newBuilder()
    .uri(URI.create("https://wangwei.one"))
    .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://wangwei.one"))
    .build();
var client = HttpClient.newHttpClient();
client.sendAsync(request, HttpResponse.BodyHandlers.ofString())
    .thenApply(HttpResponse::body)
    .thenAccept(System.out::println);
我们可以省略 .GET()  的调用,因为它默认的请求方式。

下面这个列子,我们以POST的方法向指定的URL发送数据。类似于 BodyHandlers ,你可以使用 BodyPublishers 去定义请求消息体中你想要发送的数据类型,例如 strings, byte-arrays,files 或 input-streams:

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
Collections

List, SetMap 这样的集合,它们的API也得到了扩展。List.of 可以从给定的参数中创建一个不可变的list。List.copyOf 可以创建一个 list 的不可变副本。

var list = List.of("A", "B", "C");
var copy = List.copyOf(list);
System.out.println(list == copy);   // true

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

var list = new ArrayList();
var copy = List.copyOf(list);
System.out.println(list == copy);   // false

当创建不可变的 maps 时,你不需要亲自去创建一个完整的 map 集合,你可以直接通过 Map.of 来进行创建:

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

Java8中介绍的Stream也新增了方法。Stream.ofNullable 可以从单个元素中构造一个Stream:

Stream.ofNullable(null).count(); // 0

dropWhiletakeWhile 方法可以用来决定stream中的哪些元素可以被抛弃:

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]
如果你对Streams不是很熟悉,你可以看看这篇文章 Java 8 Streams Tutorial.
Optionals

Optionals 也新增了一些非常好用的方法。例如,现在你可以简单地将 Optionals 转换为 Streams,或者使用另一个optional作为一个空optional的fallback。

Optional.of("foo").orElseThrow();     // foo
Optional.of("foo").stream().count();  // 1
Optional.ofNullable(null)
    .or(() -> Optional.of("fallback"))
    .get();                           // fallback
Strings

最基本的类之一 String 新增了一些辅助方法,用以修剪或检查空格以及对字符串进行流化处理:

" ".isBlank();                // true
" Foo Bar ".strip();          // "Foo Bar"
" Foo Bar ".stripTrailing();  // " Foo Bar"
" Foo Bar ".stripLeading();   // "Foo Bar "
"Java".repeat(3);             // "JavaJavaJava"
"A
B
C".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);
}
其他JVM特性

这些是 - 在我看来 - 从Java 8迁移到11时最有趣的语言新API功能。但是功能列表并没有在这里结束。 最新的Java版本中包含了更多内容:

Flow API for reactive programming

Java Module System

Application Class Data Sharing

Dynamic Class-File Constants

Java REPL (JShell)

Flight Recorder

Unicode 10

G1: Full Parallel Garbage Collector

ZGC: Scalable Low-Latency Garbage Collector

Epsilon: No-Op Garbage Collector

Deprecate the Nashorn JavaScript Engine

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/77361.html

相关文章

  • Spring Cloud Alibaba基础教程:Nacos的集群部署

    摘要:通过本文,我们将完成生产环境的搭建。第二步修改文件,增加支持数据源配置,添加目前只支持数据源的用户名和密码。另外,的集群需要个或个以上的节点,并且确保这三个节点之间是可以互相访问的。也可以故意的关闭某个实例,来验证集群是否还能正常服务。 前情回顾: 《Spring Cloud Alibaba基础教程:使用Nacos实现服务注册与发现》 《Spring Cloud Alibaba基础教...

    elarity 评论0 收藏0
  • Spring Cloud Alibaba基础教程:Nacos的集群部署

    摘要:通过本文,我们将完成生产环境的搭建。第二步修改文件,增加支持数据源配置,添加目前只支持数据源的用户名和密码。另外,的集群需要个或个以上的节点,并且确保这三个节点之间是可以互相访问的。也可以故意的关闭某个实例,来验证集群是否还能正常服务。 前情回顾: 《Spring Cloud Alibaba基础教程:使用Nacos实现服务注册与发现》 《Spring Cloud Alibaba基础教...

    godruoyi 评论0 收藏0
  • 11个最值得Java开发者收藏的网站

    摘要:是领域最具代表性的问答网站之一。在,开发者能够为各种相关的开源代码贡献自己的力量,也可以发布软件开发项目。该网站发布各技术领域的高技术含量内容,例如大数据,云计算,,物联网,开发等。是一个大型的资源类网站,主要涉及源代码和代码示例。 Java是一种面向对象的编程语言,由Sun Microsystems公司在1995年的时候正式发布。直到今天,Java都一直是最受欢迎的编程语言之一。如今...

    WrBug 评论0 收藏0
  • W3School 教程整理

    摘要:离线版大部分整理自,少部分整理自,由本人整理。感谢站长的无私奉献。由于本人精力有限,此处的列表不一定能够及时更新,最新版本请到本人博客查看。 离线版大部分整理自 w3cschool ,少部分整理自 w3school ,由本人整理。 感谢 w3cschool 站长的无私奉献。 由于本人精力有限,此处的列表不一定能够及时更新,最新版本请到本人博客查看。 AngularJS教程 最后更...

    douzifly 评论0 收藏0
  • W3School 教程整理

    摘要:离线版大部分整理自,少部分整理自,由本人整理。感谢站长的无私奉献。由于本人精力有限,此处的列表不一定能够及时更新,最新版本请到本人博客查看。 离线版大部分整理自 w3cschool ,少部分整理自 w3school ,由本人整理。 感谢 w3cschool 站长的无私奉献。 由于本人精力有限,此处的列表不一定能够及时更新,最新版本请到本人博客查看。 AngularJS教程 最后更...

    CoffeX 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<