手记

JDK9新特性详解与入门教程

概述

本文全面介绍了JDK9新特性,包括模块系统、新的HTTP客户端API以及移除废弃接口和类等内容,使Java应用程序的开发更加现代化和易于维护。此外,文章还详细讲解了JDK9的下载安装方法和如何使用新的API进行网络请求。通过这些新特性,开发人员可以更高效地管理和优化Java应用程序。

1. JDK9简介与下载安装

JDK9的简介

Java Development Kit(JDK)是开发和运行Java应用程序的标准平台。JDK 9是Java平台在2017年发布的最新版本,它包含了众多新特性和改进,包括模块系统(Project Jigsaw)、新的HTTP客户端API、改进的垃圾收集器等。这些特性使得Java应用程序的开发更加现代化,更易于维护和扩展。

JDK9的下载

要获取JDK 9,可以通过Oracle官方网站下载最新版本。此外,也可以通过AdoptOpenJDK项目下载,这是一个开源项目,提供了经过测试和验证的OpenJDK二进制文件。下载页面通常会提供适用于不同操作系统的安装包。

JDK9的安装方法

Windows系统安装方法

  1. 下载JDK 9安装包(.msi文件)。
  2. 双击安装包文件,启动安装向导。
  3. 选择安装路径,然后点击下一步。
  4. 选择安装组件,可以勾选安装文档,然后点击下一步。
  5. 选择安装附加任务,如设置环境变量,然后点击下一步。
  6. 点击安装,等待安装完成后,点击完成。

Linux系统安装方法

  1. 通过终端命令下载JDK 9安装包(.tar.gz文件)。
  2. 使用命令tar -xzf jdk-9_x64.tar.gz解压文件。
  3. 将解压后的文件夹复制到指定路径,如/usr/lib/jvm
  4. 设置环境变量,例如在.bashrc文件中添加如下内容:
    export JAVA_HOME=/usr/lib/jvm/jdk-9
    export PATH=$JAVA_HOME/bin:$PATH

MacOS系统安装方法

  1. 通过终端命令下载JDK 9安装包(.tar.gz文件)。
  2. 使用命令tar -xzf jdk-9_x64.tar.gz解压文件。
  3. 将解压后的文件夹复制到指定路径,如/Library/Java/JavaVirtualMachines
  4. 设置环境变量,例如在.bash_profile文件中添加如下内容:
    export JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk-9.jdk/Contents/Home
    export PATH=$JAVA_HOME/bin:$PATH
2. 模块系统(Project Jigsaw)

什么是模块系统

模块系统是Project Jigsaw的一个主要特性,它引入了模块的概念,使得Java程序的组织、依赖管理更加清晰。模块是独立的单元,它们封装了代码和资源,并声明了与其他模块的依赖关系。模块可以在编译时进行静态检查,确保没有未声明的依赖关系。

模块系统的基本概念

模块系统的一些基本概念包括:

  • 模块声明:Java程序文件的根目录下包含一个module-info.java文件,该文件声明了模块及其依赖关系。例如:

    module example.module {
    requires java.base;
    requires java.logging;
    exports example.module.package;
    }
  • 模块路径:模块路径是指定编译器和运行时查找模块的位置。例如,可以通过--module-path参数指定模块路径。

  • 模块依赖:模块之间可以通过requires关键字声明依赖关系。例如,模块A声明依赖模块B,则模块A需要使用模块B提供的功能。

如何使用模块系统

  1. 创建新的模块项目:

    • 创建一个新的Java项目,并在项目根目录下创建一个module-info.java文件。
    • module-info.java文件中声明模块及其依赖关系。
  2. 编写模块代码:

    • 在模块目录下编写Java类文件,并确保类的包结构与module-info.java中的声明一致。
  3. 编译模块:

    • 使用javac命令编译模块,需要指定模块路径。例如,对于一个简单的模块项目,编译命令可能如下:
      javac --module-path path/to/module --add-modules example.module -d out src/example/module/*.java
  4. 运行模块:
    • 使用java命令运行模块,需要指定模块路径和主模块。例如,运行上一步编译的模块命令可能如下:
      java --module-path out --module example.module/example.module.Main
3. 移除废弃接口与类

JDK9移除的接口和类

JDK 9中移除了一些不再使用的接口和类,这些接口和类在Java 8之前就已经标记为废弃(deprecated),移除它们是为了简化Java库并减少维护负担。例如,java.util.concurrent.ScheduledFutureTask类和javax.xml.ws.WebServiceException类的子类HandlerException

移除的原因及其影响

移除这些废弃接口和类的原因主要有:

  • 减少代码库的复杂性:废弃的接口和类通常不再使用,保留它们只会增加代码库的复杂性。
  • 简化维护:移除废弃接口和类可以减少维护的成本,因为这些接口和类通常不会被更新。
  • 提高性能:移除不必要的代码可以提高程序的执行效率。

移除废弃接口和类的影响:

  • 向后不兼容:使用这些废弃接口和类的旧代码将无法编译或运行。
  • 代码更新:需要更新旧代码,使用新的接口和类实现相同的功能。

用户如何应对移除的接口和类

用户需要在升级到JDK 9之前检查并更新旧代码。具体步骤如下:

  1. 检查代码依赖:使用IDE或其他工具检查代码中使用的接口和类是否已经被移除。
  2. 替换废弃接口和类:找到新的接口或类替换废弃的接口和类。例如,HandlerException可以替换为WebServiceException
  3. 更新依赖库:如果使用的第三方库依赖于被移除的接口或类,需要更新这些库到新的版本。

例如,如果代码中使用了HandlerException,可以更新为:

import javax.xml.ws.WebServiceException;

public class MyService {
  public void handleException() {
    WebServiceException e = new WebServiceException();
    // 处理异常
  }
}
4. 新的HTTP客户端API

HTTP客户端API的改进

JDK 9引入了新的HTTP客户端API(java.net.http包),它提供了一个现代的、面向流的接口,用于发送和接收HTTP请求和响应。新的API简化了HTTP客户端的开发,提供了更好的性能和安全性。

使用新API进行HTTP请求

新的HTTP客户端API提供了多种方法来发送HTTP请求,包括GETPOSTPUTDELETE等。以下是使用新API发送HTTP请求的一个基本示例:

import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.http.HttpResponse.BodyHandlers;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

public class HttpClientExample {
  public static void main(String[] args) throws ExecutionException, InterruptedException {
    HttpClient client = HttpClient.newHttpClient();

    HttpRequest request = HttpRequest.newBuilder()
      .uri(URI.create("https://www.example.com/api/data"))
      .GET()
      .build();

    // 异步请求
    CompletableFuture<HttpResponse<String>> responseFuture = client.sendAsync(request, BodyHandlers.ofString());
    HttpResponse<String> response = responseFuture.get(5, TimeUnit.SECONDS);

    System.out.println("Status code: " + response.statusCode());
    System.out.println("Response body: " + response.body());
  }
}

示例代码演示

以下是一些使用新API发送不同类型的HTTP请求的示例:

发送GET请求并获取响应体

import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

public class HttpClientGetExample {
  public static void main(String[] args) throws ExecutionException, InterruptedException {
    HttpClient client = HttpClient.newHttpClient();

    HttpRequest request = HttpRequest.newBuilder()
      .uri(URI.create("https://www.example.com/api/data"))
      .GET()
      .build();

    CompletableFuture<HttpResponse<String>> responseFuture = client.sendAsync(request, BodyHandlers.ofString());
    HttpResponse<String> response = responseFuture.get(5, TimeUnit.SECONDS);

    System.out.println("Status code: " + response.statusCode());
    System.out.println("Response body: " + response.body());
  }
}

发送POST请求并获取响应体

import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.charset.StandardCharsets;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

public class HttpClientPostExample {
  public static void main(String[] args) throws ExecutionException, InterruptedException {
    HttpClient client = HttpClient.newHttpClient();

    String jsonPayload = "{ \"key\": \"value\" }";
    HttpRequest request = HttpRequest.newBuilder()
      .uri(URI.create("https://www.example.com/api/data"))
      .POST(HttpRequest.BodyPublishers.ofString(jsonPayload, StandardCharsets.UTF_8))
      .build();

    CompletableFuture<HttpResponse<String>> responseFuture = client.sendAsync(request, BodyHandlers.ofString());
    HttpResponse<String> response = responseFuture.get(5, TimeUnit.SECONDS);

    System.out.println("Status code: " + response.statusCode());
    System.out.println("Response body: " + response.body());
  }
}

发送PUT请求并获取响应体

import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

public class HttpClientPutExample {
  public static void main(String[] args) throws ExecutionException, InterruptedException {
    HttpClient client = HttpClient.newHttpClient();

    String jsonPayload = "{ \"key\": \"value\" }";
    HttpRequest request = HttpRequest.newBuilder()
      .uri(URI.create("https://www.example.com/api/data"))
      .PUT(HttpRequest.BodyPublishers.ofString(jsonPayload, StandardCharsets.UTF_8))
      .build();

    CompletableFuture<HttpResponse<String>> responseFuture = client.sendAsync(request, BodyHandlers.ofString());
    HttpResponse<String> response = responseFuture.get(5, TimeUnit.SECONDS);

    System.out.println("Status code: " + response.statusCode());
    System.out.println("Response body: " + response.body());
  }
}

发送DELETE请求并获取响应体

import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

public class HttpClientDeleteExample {
  public static void main(String[] args) throws ExecutionException, InterruptedException {
    HttpClient client = HttpClient.newHttpClient();

    HttpRequest request = HttpRequest.newBuilder()
      .uri(URI.create("https://www.example.com/api/data"))
      .DELETE()
      .build();

    CompletableFuture<HttpResponse<String>> responseFuture = client.sendAsync(request, BodyHandlers.ofString());
    HttpResponse<String> response = responseFuture.get(5, TimeUnit.SECONDS);

    System.out.println("Status code: " + response.statusCode());
    System.out.println("Response body: " + response.body());
  }
}

这些示例展示了如何使用新的HTTP客户端API发送不同类型和参数的HTTP请求,并获取响应体。这些API提供了更灵活、更现代的HTTP客户端开发方式,使得开发人员可以更方便地进行网络请求。

5. 其他实用的新特性

移动到新的源格式

JDK 9引入了新的源格式,称为JEP 220(Java Module System)。新的源格式支持模块化,使用module-info.java文件来定义模块声明。这使得源代码更加模块化,便于管理和维护。

例如,一个模块的module-info.java文件可能如下所示:

module example.module {
  requires java.base;
  requires java.logging;
  exports example.module.package;
}

这个文件定义了一个名为example.module的模块,声明了对java.basejava.logging模块的依赖,并导出了example.module.package包。

第三方工具与库的集成

JDK 9引入了新的工具和API,使得与第三方工具和库的集成更加方便。例如,JEP 223(Lowest action in a resource leak warning)引入了新的资源泄漏检查工具,可以帮助开发者更好地管理资源。

此外,JDK 9提供了更强大的工具和API,例如JEP 217(Deprecate the Nashorn JavaScript Engine),使得与JavaScript引擎的交互更加灵活。

G1垃圾收集器的默认设置

JDK 9默认使用G1垃圾收集器。G1垃圾收集器是Java 9中的默认垃圾收集器,它提供了更高效、更稳定的垃圾收集性能。G1垃圾收集器可以自动划分堆内存,管理回收集,使得垃圾收集更加高效。

例如,可以通过以下命令启动Java应用程序,并指定使用G1垃圾收集器:

java -XX:+UseG1GC -jar myapp.jar

G1垃圾收集器的默认设置使得Java应用程序的内存管理更加稳定和高效,减少了垃圾收集对应用程序性能的影响。

6. 总结与练习

JDK9新特性的总结

JDK 9引入了众多新特性,包括模块系统、新的HTTP客户端API、移除废弃接口和类等。这些特性使得Java应用程序的开发更加现代化,更易于维护和扩展。模块系统提供了更加清晰的依赖管理,新的HTTP客户端API提供了更现代、更灵活的网络请求方式,移除废弃接口和类则简化了代码库。

实践练习建议

  1. 创建模块项目:创建一个新的Java项目,并在项目根目录下创建一个module-info.java文件。声明模块及其依赖关系,并编写模块代码。
  2. 使用新的HTTP客户端API:编写代码使用新的HTTP客户端API发送不同类型和参数的HTTP请求,并获取响应体。
  3. 移除废弃接口和类:检查并更新旧代码,移除使用废弃接口和类的部分,使用新的替代实现相同的功能。

进一步学习的资源推荐

  • 慕课网:提供丰富的Java学习资源,包括视频教程、实战项目等。
  • Java官方文档:提供了详细的Java开发指南和API文档,是学习Java的最佳资源。
  • Stack Overflow:提供了大量的Java编程问题和解决方案,是解决Java编程问题的好地方。
0人推荐
随时随地看视频
慕课网APP