Java 11 - 快速指南


Java 14 - 概述

Java 11 是继 Java 8 之后的第一个 LTS(长期支持)功能版本。它遵循 Java 发布节奏,从 Java 10 开始引入,并于 2018 年 9 月发布,距 Java 10 发布仅六个月。

Java 9 和 Java 10 是非 LTS 版本。Java 11 版本是 LTS 版本。

新功能

以下是 Java 11 中引入的主要新功能。

  • JEP 321 - HTTP 客户端 API 标准化。

  • JEP 330 - 无需编译即可启动单文件源代码程序

  • JEP 323 - Lambda 参数的局部变量语法

  • JEP 181 - 基于嵌套的访问控制

  • JEP 331 - 低开销堆分析

  • JEP 318 - Epsilon,无操作垃圾收集器

  • JEP 333 - ZGC 可扩展的低延迟垃圾收集器

  • Collection API 更新- 新的 Collection.toArray(IntFunction) 默认方法。

  • String API 更新- 添加了新方法,如重复()、isBlank()、strip()和lines()。

  • 文件 API 更新- 添加了新方法,例如 readString() 和 writeString()。

  • 可选更新- 添加了新方法 isEmpty()。

Java 11 通过新方法和选项增强了许多 API,并删除了已弃用的 API 和选项。我们将在接下来的章节中看到这些变化。

Java 11 - 环境设置

在线现场演示选项

我们已经在线设置了Java编程环境,以便您可以在线编译和执行所有可用的示例。它使您对所阅读的内容充满信心,并使您能够使用不同的选项验证程序。请随意修改任何示例并在线执行。

使用以下示例代码框右上角的“实时演示”选项尝试以下示例 -

public class MyFirstJavaProgram {
   public static void main(String []args) {
      System.out.println("Hello World");
   }
}

对于本教程中给出的大多数示例,您将在我们网站右上角的代码部分中找到“试用”选项,该选项将带您进入在线编译器。因此,请充分利用它并享受学习的乐趣。

本地环境设置

如果您想设置自己的 Java 编程语言环境,那么本节将指导您完成整个过程。请按照以下步骤设置您的 Java 环境。

Java SE 可供免费下载。要下载,请单击此处,请下载与您的操作系统兼容的版本。

按照说明下载 Java,然后运行​​.exe以在您的计算机上安装 Java。在计算机上安装 Java 后,您需要设置环境变量以指向正确的安装目录。

设置 Windows 2000/XP 的路径

假设您已将 Java 安装在 c:\Program Files\java\jdk 目录中 -

  • 右键单击“我的电脑”并选择“属性”。

  • 单击“高级”选项卡下的“环境变量”按钮。

  • 现在,编辑“Path”变量并在其末尾添加 Java 可执行文件目录的路径。例如,如果路径当前设置为C:\Windows\System32,则按以下方式编辑它

    C:\Windows\System32;c:\Program Files\java\jdk\bin

设置Windows 95/98/ME的路径

假设您已将 Java 安装在 c:\Program Files\java\jdk 目录中 -

  • 编辑“C:\autoexec.bat”文件并在末尾添加以下行 -

    设置路径=%PATH%;C:\Program Files\java\jdk\bin

设置 Linux、UNIX、Solaris、FreeBSD 的路径

应将环境变量 PATH 设置为指向 Java 二进制文件的安装位置。如果您在执行此操作时遇到问题,请参阅您的 shell 文档。

例如,如果您使用 bash 作为 shell,那么您可以在.bashrc末尾添加以下行-

    导出 PATH=/path/to/java:$PATH'

流行的 Java 编辑器

要编写 Java 程序,您需要一个文本编辑器。市场上还有更复杂的 IDE。最流行的简要描述如下 -

  • 记事本- 在 Windows 计算机上,您可以使用任何简单的文本编辑器,例如记事本(本教程推荐)或写字板。Notepad++ 也是一个免费的文本编辑器,增强了功能。

  • Netbeans - 它是一个开源且免费的 Java IDE,可以从www.netbeans.org/index.html下载。

  • Eclipse - 它也是由 Eclipse 开源社区开发的 Java IDE,可以从www.eclipse.org下载。

IDE或集成开发环境,提供所有常见的工具和设施来帮助编程,例如源代码编辑器、构建工具和调试器等。

Java 11 - 标准 HttpClient

Java 9 中引入了增强的 HttpClient API 作为实验性功能。在 Java 11 中,HttpClient 现在已成为标准。建议使用其他 HTTP 客户端 API,例如 Apache Http 客户端 API。它的功能非常丰富,现在基于 Java 的应用程序可以在不使用任何外部依赖项的情况下发出 HTTP 请求。

脚步

以下是使用 HttpClient 的步骤。

  • 使用 HttpClient.newBuilder() 实例创建 HttpClient 实例

  • 使用 HttpRequest.newBuilder() 实例创建 HttpRequest 实例

  • 使用 httpClient.send() 发出请求并获取响应对象。

例子

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;

public class APITester {
   public static void main(String[] args) {
      HttpClient httpClient = HttpClient.newBuilder()
         .version(HttpClient.Version.HTTP_2)
         .connectTimeout(Duration.ofSeconds(10))
         .build(); 
         try {
            HttpRequest request = HttpRequest.newBuilder()
            .GET()
            .uri(URI.create("https://www.google.com"))
            .build();                              
            HttpResponse<String> response = httpClient.send(request,
            HttpResponse.BodyHandlers.ofString()); 

         System.out.println("Status code: " + response.statusCode());                            
         System.out.println("Headers: " + response.headers().allValues("content-type"));
         System.out.println("Body: " + response.body());
      } catch (IOException | InterruptedException e) {
         e.printStackTrace();
      }
   }
}

输出

它将打印以下输出。

Status code: 200
Headers: [text/html; charset=ISO-8859-1]
Body: <!doctype html>
...
</html>

Java 11 - 编译免费启动

从 Java 11 开始,现在无需编译即可轻松测试单个 java 文件。考虑以下示例 -

ApiTester.java

public class Tester {
   public static void main(String[] args) {
     System.out.println("Hello World!"); 
   }
}

旧的运行文件方式

$ javac ApiTester.java
$ java Tester
Hello World!

运行文件的新方式

$ java ApiTester.java
Hello World!

这一新功能将帮助开发人员快速测试功能,而无需在运行代码之前进行编译。

Java 11 - 字符串 API

Java 11 对 String 引入了多项增强功能。

  • String.repeat(int) - 重复字符串给定的次数。返回连接的字符串。

  • String.isBlank() - 检查字符串是否为空或仅包含空格。

  • String.strip() - 删除前导和尾随空格。

  • String.stripLeading() - 删除前导空格。

  • String.stripTrailing() - 删除尾随空格。

  • String.lines() - 返回多行字符串的行流。

考虑以下示例 -

ApiTester.java

import java.util.ArrayList;
import java.util.List;

public class APITester {
   public static void main(String[] args) {
      String sample = " abc ";
      System.out.println(sample.repeat(2)); // " abc  abc "
      System.out.println(sample.isBlank()); // false
      System.out.println("".isBlank()); // true
      System.out.println("   ".isBlank()); // true
      System.out.println(sample.strip()); // "abc"
      System.out.println(sample.stripLeading()); // "abc "
      System.out.println(sample.stripTrailing()); // " abc"
      sample = "This\nis\na\nmultiline\ntext.";

      List<String> lines = new ArrayList<>();

      sample.lines().forEach(line -> lines.add(line));
      lines.forEach(line -> System.out.println(line));
   }
}

输出

abc  abc 
false
true
true
abc
abc 
 abc
This
is
a
multiline
text.

Java 11 - 集合到数组

Java 11 引入了一种将集合转换为数组的简单方法。

老方法

nameArray = nameList.toArray(new String[nameList.size()]);

新方法

nameArray = nameList.toArray(String[]::new);

考虑以下示例 -

ApiTester.java

import java.util.Arrays;
import java.util.List;

public class APITester {
   public static void main(String[] args) {		
      List<String> namesList = Arrays.asList("Joe", "Julie");
      // Old way
      String[] names = namesList.toArray(new String[namesList.size()]);
      System.out.println(names.length);
      // New way
      names = namesList.toArray(String[]::new);
      System.out.println(names.length);
   }
}

输出

2
2

Java 11 - 文件 API

Java 11 通过提供新的重载方法引入了一种读取和写入文件的简单方法,而无需编写大量样板代码。

考虑以下示例 -

ApiTester.java

import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;

public class APITester {
   public static void main(String[] args) {		
      try {
         Path tempFilePath = Files.writeString(
            Path.of(File.createTempFile("tempFile", ".tmp").toURI()),
            "Welcome to TutorialsPoint", 
            Charset.defaultCharset(), StandardOpenOption.WRITE);

         String fileContent = Files.readString(tempFilePath);

         System.out.println(fileContent);
      } catch (IOException e) {
         e.printStackTrace();
      }
   }
}

输出

Welcome to TutorialsPoint

Java 11 - 可选类

Java 11 向Optional 类引入了新方法isEmpty() 来检查值是否存在。如果值存在,isEmpty() 返回 false,否则返回 true。

它可以用作 isPresent() 方法的替代方法,该方法通常需要否定来检查值是否不存在。

考虑以下示例 -

ApiTester.java

import java.util.Optional;

public class APITester {
   public static void main(String[] args) {		
      String name = null;

      System.out.println(!Optional.ofNullable(name).isPresent());
      System.out.println(Optional.ofNullable(name).isEmpty());

      name = "Joe";
      System.out.println(!Optional.ofNullable(name).isPresent());
      System.out.println(Optional.ofNullable(name).isEmpty());
   }
}

输出

true
true
false
false

Java 11 - 非谓词

Java 11 向 Predicate 接口引入了新方法 not() 来否定现有谓词,类似于 negate 方法。

考虑以下示例 -

ApiTester.java

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

public class APITester {
   public static void main(String[] args) {		
      List<String> tutorialsList = Arrays.asList("Java", "\n", "HTML", " ");

      List<String> tutorials = tutorialsList.stream()
         .filter(Predicate.not(String::isBlank))
         .collect(Collectors.toList());

      tutorials.forEach(tutorial -> System.out.println(tutorial));
   }
}

输出

Java
HTML

Java 11 - Lambda 中的 Var

Java 11 允许在 lambda 表达式中使用 var,并且可用于将修饰符应用于局部变量。

(@NonNull var value1, @Nullable var value2) -> value1 + value2

考虑以下示例 -

ApiTester.java

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

@interface NonNull {}

public class APITester {
   public static void main(String[] args) {		
      List<String> tutorialsList = Arrays.asList("Java", "HTML");

      String tutorials = tutorialsList.stream()
         .map((@NonNull var tutorial) -> tutorial.toUpperCase())
         .collect(Collectors.joining(", "));

      System.out.println(tutorials);
   }
}

输出

Java
HTML

局限性

在 lambda 表达式中使用 var 有一定的限制。

  • var 参数不能与其他参数混合。以下将抛出编译错误。

(var v1, v2) -> v1 + v2
  • var 参数不能与其他类型参数混合。以下将抛出编译错误。

(var v1, String v2) -> v1 + v2
  • var 参数只能与括号一起使用。以下将抛出编译错误。

var v1 -> v1.toLowerCase()

Java 11 - 基于嵌套的访问

Java 11 引入了嵌套类的概念,我们可以在类中声明类。这种类的嵌套允许将要在一个地方使用的类按逻辑分组,从而使它们更具可读性和可维护性。嵌套类可以有四种类型 -

  • 静态嵌套类

  • 非静态嵌套类

  • 本地课程

  • 匿名类

Java 11 还提供了 Nestmate 的概念,以允许嵌套类的通信和验证。

考虑以下示例 -

ApiTester.java

import java.util.Arrays;
import java.util.Set;
import java.util.stream.Collectors;

public class APITester {
   public static void main(String[] args) {		
      boolean isNestMate = APITester.class.isNestmateOf(APITester.Inner.class);
      boolean nestHost = APITester.Inner.class.getNestHost() == APITester.class;

      System.out.println(isNestMate);
      System.out.println(nestHost);

      Set<String> nestedMembers = Arrays.stream(APITester.Inner.class.getNestMembers())
         .map(Class::getName)
         .collect(Collectors.toSet());
      System.out.println(nestedMembers);
   }
   public class Inner{}
}

输出

true
true
[APITester$Inner, APITester]

Java 11 - 删除/弃用的 API

Java 11 删除了选定的已弃用的 API。以下是已删除的 API 的列表。

Java EE 和 CORBA

以下已弃用的 Java EE 和 CORBA 已从 Java 11 版本中删除。

  • 用于基于 XML 的 Web 服务的 Java API (java.xml.ws)

  • XML 绑定的 Java 体系结构 (java.xml.bind)

  • JavaBeans 激活框架 (java.activation)

  • 常用注解 (java.xml.ws.annotation)

  • 通用对象请求代理架构 (java.corba)

  • JavaTransaction API (java.transaction)

这些 API 可作为第三方网站的独立版本使用。

JMC 和 JavaFX

  • JDK Mission Control (JMC) 已从标准 JDK 中删除。它可以单独下载。

  • JavaFX 也从标准 JDK 中删除。它可以作为单独的模块进行下载。

已弃用的模块

  • Nashorn JavaScript 引擎和 JJS 工具已弃用。

  • JAR 文件的 Pack200 压缩方案已弃用。