Java 9 - Hướng dẫn nhanh

JAVA 9 (hay còn gọi là jdk 1.9) là một bản phát hành chính của việc phát triển ngôn ngữ lập trình JAVA. Phiên bản đầu tiên của nó được phát hành vào ngày 21 tháng 9 năm 2017. Các mục tiêu chính của bản phát hành Java 9 là:

  • Để làm cho nền tảng JDK và Java Standard Edition dựa trên mô-đun để có thể áp dụng tốt cho các thiết bị máy tính nhỏ.

  • Để cải thiện tính bảo mật tổng thể của Triển khai JDK và Java.

  • Để làm cho quá trình xây dựng và bảo trì các thư viện mã java và các ứng dụng lớn trở nên dễ dàng cho các nền tảng JAVA SE và EE.

  • Để thiết kế và triển khai hệ thống mô-đun tiêu chuẩn cho Nền tảng Java có thể được áp dụng trên cả Nền tảng và JDK một cách dễ dàng.

Các tính năng mới

Có hơn 90 cải tiến được thêm vào Java 8, những cải tiến quan trọng nhất được đề cập bên dưới -

  • Module - Một loại thành phần lập trình Java mới được giới thiệu dưới dạng mô-đun, là một tập hợp mã và dữ liệu được đặt tên, tự mô tả.

  • REPL (JShell) - Khả năng Read-Eval-Print Loop (REPL) được thêm vào nền tảng Java.

  • HTTP 2 Client - API HTTPClient mới hỗ trợ websockets và luồng HTTP 2 và các tính năng đẩy máy chủ.

  • Improved JavaDocs- Hỗ trợ tạo đầu ra HTML5. Cung cấp hộp tìm kiếm cho tài liệu API đã tạo.

  • Multirelease JAR - Nâng cao định dạng JAR để nhiều phiên bản dành riêng cho bản phát hành Java của các tệp lớp có thể cùng tồn tại trong một kho lưu trữ duy nhất.

  • Collection Factory Methods - Các phương thức nhà máy tĩnh mới cho các giao diện Danh sách, Tập hợp và Bản đồ để tạo các thể hiện bất biến của các tập hợp đó.

  • Private Interface Methods - Giao diện nâng cao với các phương thức tĩnh riêng tư và riêng tư.

  • Process API Improvements - Cải tiến API để kiểm soát và quản lý các quy trình của hệ điều hành.

  • Stream API Improvements - Tăng cường bảo mật và mạnh mẽ bằng cách cho phép lọc các luồng dữ liệu tuần tự hóa đối tượng đến.

  • Try With Resources improvement - Bây giờ các biến cuối cùng có thể được sử dụng làm tài nguyên trong câu lệnh try-with-resources.

  • Enhanced @Deprecated Annotation - @ Chú thích không được sử dụng được cải tiến để cung cấp thêm thông tin về trạng thái và cách xử lý dự định của một API.

  • Inner Class Diamond Operator - Cho phép toán tử kim cương được sử dụng với các lớp ẩn danh nếu kiểu đối số của kiểu suy ra có thể được ký hiệu.

  • Optional Class Improvements - Các phương thức hữu ích mới được thêm vào lớp java.util.Optional.

  • Multiresolution Image API - Hỗ trợ đóng gói một tập hợp các hình ảnh có độ phân giải khác nhau thành một hình ảnh đa phân giải duy nhất.

  • CompletableFuture API improvements - Các cơ chế không đồng bộ của lớp CompletableFuture có thể thực hiện một hành động khi tiến trình thoát bằng phương thức ProcessHandle.onExit.

  • Lightweight JSON - Một API nhẹ được giới thiệu để sử dụng và tạo các tài liệu và luồng dữ liệu thông qua json trong java 9.

  • Reactive Streams API - Một API Reactive Streams mới trong Java SE 9 đã được giới thiệu để hỗ trợ lập trình phản ứng trong java 9.

Thiết lập môi trường cục bộ

Nếu bạn muốn thiết lập môi trường riêng cho ngôn ngữ lập trình Java, thì phần này sẽ hướng dẫn bạn toàn bộ quá trình. Vui lòng làm theo các bước dưới đây để thiết lập môi trường Java của bạn.

Java SE có sẵn để tải xuống miễn phí. Để tải xuống, nhấp vào đây , vui lòng tải xuống phiên bản tương thích với hệ điều hành của bạn.

Làm theo hướng dẫn để tải xuống Java và chạy .exeđể cài đặt Java trên máy của bạn. Khi bạn đã cài đặt Java trên máy của mình, bạn sẽ cần đặt các biến môi trường để trỏ đến các thư mục cài đặt chính xác.

Thiết lập đường dẫn cho Windows 2000 / XP

Giả sử bạn đã cài đặt Java trong thư mục c: \ Program Files \ java \ jdk -

  • Nhấp chuột phải vào 'Máy tính của tôi' và chọn 'Thuộc tính'.

  • Nhấp vào nút 'Biến môi trường' trong tab 'Nâng cao'.

  • Bây giờ, hãy chỉnh sửa biến 'Đường dẫn' và thêm đường dẫn vào thư mục thực thi Java ở cuối biến. Ví dụ: nếu đường dẫn hiện được đặt thành C:\Windows\System32, thì hãy chỉnh sửa nó theo cách sau

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

Thiết lập đường dẫn cho Windows 95/98 / ME

Giả sử bạn đã cài đặt Java trong thư mục c: \ Program Files \ java \ jdk -

  • Chỉnh sửa tệp 'C: \ autoexec.bat' và thêm dòng sau vào cuối -

SET PATH = %PATH%;C:\Program Files\java\jdk\bin

Thiết lập đường dẫn cho Linux, UNIX, Solaris, FreeBSD

Biến môi trường PATH nên được đặt để trỏ đến nơi các tệp nhị phân Java đã được cài đặt. Tham khảo tài liệu shell của bạn nếu bạn gặp khó khăn khi thực hiện việc này.

Ví dụ: nếu bạn sử dụng bash làm trình bao, thì bạn sẽ thêm dòng sau vào cuối .bashrc -

export PATH = /path/to/java:$PATH'

Trình chỉnh sửa Java phổ biến

Để viết các chương trình Java, bạn cần một trình soạn thảo văn bản. Thậm chí có nhiều IDE phức tạp hơn có sẵn trên thị trường. Những cái phổ biến nhất được mô tả ngắn gọn bên dưới:

  • Notepad- Trên máy Windows, bạn có thể sử dụng bất kỳ trình soạn thảo văn bản đơn giản nào như Notepad (được khuyến nghị cho hướng dẫn này) hoặc WordPad. Notepad ++ cũng là một trình soạn thảo văn bản miễn phí có các tiện ích nâng cao.

  • Netbeans - Đây là một IDE Java mã nguồn mở và miễn phí có thể được tải xuống từ https://www.netbeans.org/index.html.

  • Eclipse - Nó cũng là một IDE Java được phát triển bởi cộng đồng nguồn mở Eclipse và có thể được tải xuống từ https://www.eclipse.org/.

IDE hoặc Môi trường phát triển tích hợp, cung cấp tất cả các công cụ và phương tiện phổ biến để hỗ trợ lập trình, chẳng hạn như trình soạn thảo mã nguồn, công cụ xây dựng và trình gỡ lỗi, v.v.

Java 9, một loại thành phần lập trình mới được gọi là mô-đun đã được giới thiệu. Mô-đun là một tập hợp mã và dữ liệu tự mô tả và có tên để xác định nó.

Đặc trưng

Với thành phần Mô-đun, các cải tiến sau đã được thêm vào trong Java 9:

  • Một giai đoạn tùy chọn mới, thời gian liên kết, được giới thiệu. Giai đoạn này nằm giữa thời gian biên dịch và thời gian chạy. Trong giai đoạn này, một tập hợp các mô-đun có thể được lắp ráp và tối ưu hóa, tạo ra hình ảnh thời gian chạy tùy chỉnh bằng công cụ jlink.

  • javac, jlink và java có các tùy chọn bổ sung để chỉ định đường dẫn mô-đun, giúp định vị thêm các định nghĩa của mô-đun.

  • Định dạng JAR được cập nhật dưới dạng JAR mô-đun, chứa tệp module-info.class trong thư mục gốc của nó.

  • Định dạng JMOD được giới thiệu, một định dạng đóng gói (tương tự như JAR) có thể bao gồm mã gốc và các tệp cấu hình.

Tạo mô-đun

Làm theo các bước để tạo một mô-đun, nói com.tutorialspoint.greetings.

Bước 1

Tạo một thư mục C: \> JAVA \ src. Bây giờ, hãy tạo một thư mục com.tutorialspoint.greetings giống như tên của mô-đun chúng ta đang tạo.

Bước 2

Tạo module-info.java trong thư mục C: \> JAVA \ src \ com.tutorialspoint.greetings với mã sau.

module-info.java

module com.tutorialspoint.greetings { }

module-info.java là tệp được sử dụng để tạo mô-đun. Trong bước này, chúng tôi đã tạo một mô-đun có tên com.tutorialspoint.greetings. Theo quy ước, tệp này phải nằm trong thư mục có tên giống với tên mô-đun.

Bước 3

Thêm mã nguồn trong mô-đun. Tạo Java9Tester.java trong thư mục C: \> JAVA \ src \ com.tutorialspoint.greetings \ com \ tutorialspoint \ Welcome với mã sau.

Java9Tester.java

package com.tutorialspoint.greetings;

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

Theo quy ước, mã nguồn của một mô-đun nằm trong cùng một thư mục là tên của mô-đun.

Bước 4

Tạo một thư mục C: \> JAVA \ mods. Bây giờ, hãy tạo một thư mục com.tutorialspoint.greetings giống như tên của mô-đun chúng ta đã tạo. Bây giờ biên dịch mô-đun vào thư mục mod.

C:/ > JAVA > javac -d mods/com.tutorialspoint.greetings 
   src/com.tutorialspoint.greetings/module-info.java 
   src/com.tutorialspoint.greetings/com/tutorialspoint/greetings/Java9Tester.java

Bước 5

Hãy chạy mô-đun để xem kết quả. Chạy lệnh sau.

C:/ > JAVA > java --module-path mods -m com.tutorialspoint.greetings/com.tutorialspoint.greetings.Java9Tester

Ở đây module-path cung cấp vị trí module dưới dạng mod và -m biểu thị module chính.

Đầu ra

Nó sẽ in đầu ra sau trên bảng điều khiển.

Hello World!

REPL là viết tắt của Read-Eval-Print Loop. Với JShell, java có khả năng REPL. Sử dụng REPL, chúng ta có thể viết mã và kiểm tra logic dựa trên java mà không cần biên dịch bằng javac và xem trực tiếp kết quả tính toán.

Đang chạy JShell

Mở dấu nhắc lệnh và nhập jshell.

$ jshell
|  Welcome to JShell -- Version 9-ea
|  For an introduction type: /help intro
jshell>

Xem các lệnh JShell

Nhập / trợ giúp khi lệnh jshell bắt đầu chạy.

jshell> /help
|  Type a Java language expression, statement, or declaration.
|  Or type one of the following commands:
|  /list [<name or id>|-all|-start]
|  list the source you have typed
|  /edit <name or id>
|  edit a source entry referenced by name or id
|  /drop <name or id>
|  delete a source entry referenced by name or id
|  /save [-all|-history|-start] <file>
|  Save snippet source to a file.
|  /open <file>
|  open a file as source input
|  /vars [<name or id>|-all|-start]
|  list the declared variables and their values
|  /methods [<name or id>|-all|-start]
|  list the declared methods and their signatures
|  /types [<name or id>|-all|-start]
|  list the declared types
|  /imports 
|  list the imported items

Chạy lệnh JShell

Nhập / nhập khi lệnh jshell bắt đầu chạy và xem các nhập đã sử dụng.

jshell> /imports
|    import java.io.*
|    import java.math.*
|    import java.net.*
|    import java.nio.file.*
|    import java.util.*
|    import java.util.concurrent.*
|    import java.util.function.*
|    import java.util.prefs.*
|    import java.util.regex.*
|    import java.util.stream.*
jshell>

Chạy tính toán trong JShell.

Hãy thử chạy các phép tính đơn giản trong JShell.

jshell> 3+1
$1 ==> 4 jshell> 13%7 $2 ==> 6
jshell> $2 $2 ==> 6
jshell>

Tạo và sử dụng các hàm trong JShell

Tạo một hàm double () để lấy int và trả về giá trị nhân đôi của nó.

jshell> int doubled(int i){ return i*2;}
|  created method doubled(int)
jshell> doubled(6)
$3 ==> 12
jshell>

Thoát JShell

Nhập / thoát.

jshell> /exit
| Goodbye

Tài liệu Java có thể được tạo bằng công cụ javadoc. Nó hiện tạo tài liệu ở định dạng html 4.0. Trong java 9, chúng ta có thể tạo tài liệu ở định dạng html 5 bằng cách sử dụng tùy chọn -html5 trong đối số dòng lệnh.

Tài liệu java kiểu cũ

Hãy xem xét đoạn mã sau trong thư mục C: / JAVA.

Tester.java

/**
 * @author MahKumar
 * @version 0.1
 */
public class Tester {
   /**
   * Default method to be run to print 
   * <p>Hello world</p>
   * @param args command line arguments
   */
   public static void main(String []args) {
      System.out.println("Hello World");
   }
}

Bây giờ chạy công cụ javadoc của jdk 7 để tạo tài liệu.

C:\JAVA>javadoc -d C:/JAVA Tester.java
Loading source file tester.java...
Constructing Javadoc information...
Standard Doclet version 1.7.0_21
Building tree for all the packages and classes...
Generating C:\JAVA\Tester.html...
Generating C:\JAVA\package-frame.html...
Generating C:\JAVA\package-summary.html...
Generating C:\JAVA\package-tree.html...
Generating C:\JAVA\constant-values.html...
Building index for all the packages and classes...
Generating C:\JAVA\overview-tree.html...
Generating C:\JAVA\index-all.html...
Generating C:\JAVA\deprecated-list.html...
Building index for all classes...
Generating C:\JAVA\allclasses-frame.html...
Generating C:\JAVA\allclasses-noframe.html...
Generating C:\JAVA\index.html...
Generating C:\JAVA\help-doc.html...

Nó sẽ tạo trang tài liệu java trong thư mục C: / JAVA và bạn sẽ thấy kết quả sau.

Tài liệu java mới với hỗ trợ Tìm kiếm và HTML5

Chạy công cụ javadoc của jdk 9 với cờ -html5 để tạo loại tài liệu mới.

C:\JAVA> javadoc -d C:/JAVA -html5 Tester.java
Loading source file Tester.java...
Constructing Javadoc information...
Standard Doclet version 9.0.1
Building tree for all the packages and classes...
Generating C:\JAVA\Tester.html...
Generating C:\JAVA\package-frame.html...
Generating C:\JAVA\package-summary.html...
Generating C:\JAVA\package-tree.html...
Generating C:\JAVA\constant-values.html...
Building index for all the packages and classes...
Generating C:\JAVA\overview-tree.html...
Generating C:\JAVA\index-all.html...
Generating C:\JAVA\deprecated-list.html...
Building index for all classes...
Generating C:\JAVA\allclasses-frame.html...
Generating C:\JAVA\allclasses-frame.html...
Generating C:\JAVA\allclasses-noframe.html...
Generating C:\JAVA\allclasses-noframe.html...
Generating C:\JAVA\index.html...
Generating C:\JAVA\help-doc.html...

Nó sẽ tạo trang tài liệu java cập nhật trong thư mục D: / test và bạn sẽ thấy kết quả sau.

Trong java 9, một tính năng mới được giới thiệu trong đó định dạng jar đã được cải tiến để có các phiên bản khác nhau của lớp java hoặc các tài nguyên có thể được duy trì và sử dụng theo nền tảng. Trong JAR, tệp MANIFEST.MF tệp có mục nhập Multi-Release: true trong phần chính của nó. Thư mục META-INF cũng chứa thư mục con phiên bản có thư mục con (bắt đầu bằng 9 cho Java 9) lưu trữ các lớp và tệp tài nguyên dành riêng cho phiên bản.

Trong ví dụ này, chúng tôi sẽ sử dụng một jar nhiều bản phát hành để có hai phiên bản của tệp Tester.java, một cho jdk 7 và một cho jdk 9 và chạy nó trên các phiên bản jdk khác nhau.

Các bước

Step 1- Tạo thư mục c: / test / java7 / com / tutorialspoint. Tạo Test.java với nội dung sau:

Tester.java

package com.tutorialspoint;

public class Tester {
   public static void main(String[] args) {
      System.out.println("Inside java 7");
   }
}

Step 2- Tạo thư mục c: / test / java9 / com / tutorialspoint. Tạo Test.java với nội dung sau:

Tester.java

package com.tutorialspoint;

public class Tester {
   public static void main(String[] args) {
      System.out.println("Inside java 9");
   }
}

Biên dịch mã nguồn.

C:\test > javac --release 9 java9/com/tutorialspoint/Tester.java

C:\JAVA > javac --release 7 java7/com/tutorialspoint/Tester.java

Tạo bình nhiều bản phát hành

C:\JAVA > jar -c -f test.jar -C java7 . --release 9 -C java9.
Warning: entry META-INF/versions/9/com/tutorialspoint/Tester.java, 
   multiple resources with same name

Chạy với JDK 7

C:\JAVA > java -cp test.jar com.tutorialspoint.Tester
Inside Java 7

Chạy với JDK 9

C:\JAVA > java -cp test.jar com.tutorialspoint.Tester
Inside Java 9

Với Java 9, các phương thức gốc mới được thêm vào các giao diện List, Set và Map để tạo ra các thể hiện bất biến. Các phương pháp nhà máy này là các phương pháp nhà máy tiện lợi để tạo ra một bộ sưu tập theo cách ngắn gọn và dài dòng hơn.

Cách cũ để tạo bộ sưu tập

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

public class Tester {

   public static void main(String []args) {
      Set<String> set = new HashSet<>();
      set.add("A");
      set.add("B");
      set.add("C");
      set = Collections.unmodifiableSet(set);
      System.out.println(set);
      List<String> list = new ArrayList<>();

      list.add("A");
      list.add("B");
      list.add("C");
      list = Collections.unmodifiableList(list);
      System.out.println(list);
      Map<String, String> map = new HashMap<>();

      map.put("A","Apple");
      map.put("B","Boy");
      map.put("C","Cat");
      map = Collections.unmodifiableMap(map);
      System.out.println(map);
   }
}

Đầu ra

Nó sẽ in kết quả sau.

[A, B, C]
[A, B, C]
{A=Apple, B=Boy, C=Cat}

Phương pháp mới

Với java 9, các phương thức sau được thêm vào các giao diện Danh sách, Đặt và Bản đồ cùng với các đối tác được nạp chồng của chúng.

static <E> List<E> of(E e1, E e2, E e3);
static <E> Set<E>  of(E e1, E e2, E e3);
static <K,V> Map<K,V> of(K k1, V v1, K k2, V v2, K k3, V v3);
static <K,V> Map<K,V> ofEntries(Map.Entry<? extends K,? extends V>... entries)

Điểm cần lưu ý

  • Đối với giao diện List và Set, phương thức of (...) được nạp chồng để có từ 0 đến 10 tham số và một với tham số var args.

  • Đối với giao diện Bản đồ, phương thức of (...) được nạp chồng để có từ 0 đến 10 tham số.

  • Trong trường hợp có hơn 10 tham số cho giao diện Bản đồ, phương thức ofEntries (...) có thể được sử dụng chấp nhận tham số var args.

Cách mới để tạo bộ sưu tập

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.AbstractMap;
import java.util.Map;
import java.util.Set;

public class Tester {

   public static void main(String []args) {
      Set<String> set = Set.of("A", "B", "C");      
      System.out.println(set);
      List<String> list = List.of("A", "B", "C");
      System.out.println(list);
      Map<String, String> map = Map.of("A","Apple","B","Boy","C","Cat");
      System.out.println(map);
  
      Map<String, String> map1 = Map.ofEntries (
         new AbstractMap.SimpleEntry<>("A","Apple"),
         new AbstractMap.SimpleEntry<>("B","Boy"),
         new AbstractMap.SimpleEntry<>("C","Cat"));
      System.out.println(map1);
   }
}

Đầu ra

Nó sẽ in kết quả sau.

[A, B, C]
[A, B, C]
{A=Apple, B=Boy, C=Cat}
{A=Apple, B=Boy, C=Cat}

Trước java 8, các giao diện có thể có kiểu biến / phương thức sau.

  • Không biến đổi
  • Phương pháp trừu tượng

Vì vậy, chúng ta không thể có triển khai phương thức trong các giao diện hay chính xác hơn là một triển khai mặc định trước Java 8. Xem ví dụ.

public class Tester {
   public static void main(String []args) {
      LogOracle log = new LogOracle();
      log.logInfo("");
      log.logWarn("");
      log.logError("");
      log.logFatal("");
      LogMySql log1 = new LogMySql();
      log1.logInfo("");
      log1.logWarn("");
      log1.logError("");
      log1.logFatal("");
   }
}

final class LogOracle implements Logging {
   @Override
   public void logInfo(String message) {
      getConnection();
      System.out.println("Log Message : " + "INFO");
      closeConnection();
   }

   @Override
   public void logWarn(String message) {
      getConnection();
      System.out.println("Log Message : " + "WARN");
      closeConnection();
   }

   @Override
   public void logError(String message) {
      getConnection();
      System.out.println("Log Message : " + "ERROR");
      closeConnection();
   }

   @Override
   public void logFatal(String message) {
      getConnection();
      System.out.println("Log Message : " + "FATAL");
      closeConnection();
   }

   @Override
   public void getConnection() {
      System.out.println("Open Database connection");
   }

   @Override
   public void closeConnection() {
      System.out.println("Close Database connection");
   }
}

final class LogMySql implements Logging {
   @Override
   public void logInfo(String message) {
      getConnection();
      System.out.println("Log Message : " + "INFO");
      closeConnection();
   }

   @Override
   public void logWarn(String message) {
      getConnection();
      System.out.println("Log Message : " + "WARN");
      closeConnection();
   }

   @Override
   public void logError(String message) {
      getConnection();
      System.out.println("Log Message : " + "ERROR");
      closeConnection();
   }

   @Override
   public void logFatal(String message) {
      getConnection();
      System.out.println("Log Message : " + "FATAL");
      closeConnection();
   }

   @Override
   public void getConnection() {
      System.out.println("Open Database connection");
   }

   @Override
   public void closeConnection() {
      System.out.println("Close Database connection");
   }
}

interface Logging {
   String ORACLE = "Oracle_Database";
   String MYSQL = "MySql_Database";

   void logInfo(String message);
   void logWarn(String message);
   void logError(String message);
   void logFatal(String message);

   void getConnection();
   void closeConnection();
}

Đầu ra

Bạn sẽ thấy kết quả sau.

Open Database connection
Log Message : INFO
Close Database connection
Open Database connection
Log Message : WARN
Close Database connection
Open Database connection
Log Message : ERROR
Close Database connection
Open Database connection
Log Message : FATAL
Close Database connection

Trong ví dụ trên, mỗi phương thức nhật ký có cách triển khai riêng. Với Java 8, các giao diện có thể có kiểu biến / phương thức sau.

  • Không biến đổi
  • Phương pháp trừu tượng
  • Phương pháp mặc định
  • Phương pháp tĩnh

Hãy có cài đặt mặc định và các phương thức tĩnh trong chính giao diện sử dụng Java 8.

public class Tester {
   public static void main(String []args) {
      LogOracle log = new LogOracle();
      log.logInfo("");
      log.logWarn("");
      log.logError("");
      log.logFatal("");
      LogMySql log1 = new LogMySql();
      log1.logInfo("");
      log1.logWarn("");
      log1.logError("");
      log1.logFatal("");
   }
}

final class LogOracle implements Logging { 
}

final class LogMySql implements Logging { 
}

interface Logging {
   String ORACLE = "Oracle_Database";
   String MYSQL = "MySql_Database";

   default void logInfo(String message) {
      getConnection();
      System.out.println("Log Message : " + "INFO");
      closeConnection();
   }
   
   default void logWarn(String message) {
      getConnection();
      System.out.println("Log Message : " + "WARN");
      closeConnection();
   }
   
   default void logError(String message) {
      getConnection();
      System.out.println("Log Message : " + "ERROR");
      closeConnection();
   }
   
   default void logFatal(String message) {
      getConnection();
      System.out.println("Log Message : " + "FATAL");
      closeConnection();
   }

   static void getConnection() {
      System.out.println("Open Database connection");
   }
   static void closeConnection() {
      System.out.println("Close Database connection");
   }
}

Đầu ra

Bạn sẽ thấy kết quả sau.

Open Database connection
Log Message : INFO
Close Database connection
Open Database connection
Log Message : WARN
Close Database connection
Open Database connection
Log Message : ERROR
Close Database connection
Open Database connection
Log Message : FATAL
Close Database connection

Trong ví dụ trên, chúng tôi đang lặp lại một lần nữa. Với Java 9, các giao diện có thể có kiểu biến / phương thức sau.

  • Không biến đổi
  • Phương pháp trừu tượng
  • Phương pháp mặc định
  • Phương pháp tĩnh
  • Phương pháp riêng tư
  • Phương thức tĩnh riêng

Hãy có các phương thức riêng và sử dụng chúng trong Java 9.

public class Tester {
   public static void main(String []args) {
      LogOracle log = new LogOracle();
      log.logInfo("");
      log.logWarn("");
      log.logError("");
      log.logFatal("");
      LogMySql log1 = new LogMySql();
      log1.logInfo("");
      log1.logWarn("");
      log1.logError("");
      log1.logFatal("");
   }
}

final class LogOracle implements Logging { 
}

final class LogMySql implements Logging { 
}

interface Logging {
   String ORACLE = "Oracle_Database";
   String MYSQL = "MySql_Database";

   private void log(String message, String prefix) {
      getConnection();
      System.out.println("Log Message : " + prefix);
      closeConnection();
   }
   
   default void logInfo(String message) {
      log(message, "INFO");
   }
   
   default void logWarn(String message) {
      log(message, "WARN");
   }
   
   default void logError(String message) {
      log(message, "ERROR");
   }
   
   default void logFatal(String message) {
      log(message, "FATAL");
   }

   private static void getConnection() {
      System.out.println("Open Database connection");
   }
   
   private static void closeConnection() {
      System.out.println("Close Database connection");
   }
}

Đầu ra

Bạn sẽ thấy kết quả sau.

Open Database connection
Log Message : INFO
Close Database connection
Open Database connection
Log Message : WARN
Close Database connection
Open Database connection
Log Message : ERROR
Close Database connection
Open Database connection
Log Message : FATAL
Close Database connection

Trong Java 9 Process API chịu trách nhiệm kiểm soát và quản lý các quy trình của hệ điều hành đã được cải thiện đáng kể. ProcessHandle Class hiện cung cấp ID quy trình gốc của quy trình, thời gian bắt đầu, thời gian CPU tích lũy, đối số, lệnh, người dùng, quy trình mẹ và con cháu. Lớp ProcessHandle cũng cung cấp phương pháp để kiểm tra tính sống của các quy trình và hủy các quy trình. Nó có phương thức onExit, lớp CompletableFuture có thể thực hiện hành động không đồng bộ khi quá trình thoát.

Tester.java

import java.time.ZoneId;
import java.util.stream.Stream;
import java.util.stream.Collectors;
import java.io.IOException;

public class Tester {
   public static void main(String[] args) throws IOException {
      ProcessBuilder pb = new ProcessBuilder("notepad.exe");
      String np = "Not Present";
      Process p = pb.start();
      ProcessHandle.Info info = p.info();
      System.out.printf("Process ID : %s%n", p.pid());
      System.out.printf("Command name : %s%n", info.command().orElse(np));
      System.out.printf("Command line : %s%n", info.commandLine().orElse(np));

      System.out.printf("Start time: %s%n",
         info.startInstant().map(i -> i.atZone(ZoneId.systemDefault())
         .toLocalDateTime().toString()).orElse(np));

      System.out.printf("Arguments : %s%n",
         info.arguments().map(a -> Stream.of(a).collect(
            Collectors.joining(" "))).orElse(np));

      System.out.printf("User : %s%n", info.user().orElse(np));
   } 
}

Đầu ra

Bạn sẽ thấy kết quả sau.

Process ID : 5800
Command name : C:\Windows\System32\notepad.exe
Command line : Not Present
Start time: 2017-11-04T21:35:03.626
Arguments : Not Present
User: administrator

Các luồng được giới thiệu trong Java để giúp các nhà phát triển thực hiện các hoạt động tổng hợp từ một chuỗi các đối tượng. Với Java 9, một số phương thức khác được thêm vào để làm cho các luồng tốt hơn.

takeWhile (Giao diện dự đoán)

Cú pháp

default Stream<T> takeWhile(Predicate<? super T> predicate)

Phương thức takeWhile nhận tất cả các giá trị cho đến khi vị từ trả về false. Nó trả về, trong trường hợp luồng có thứ tự, một luồng bao gồm tiền tố dài nhất của các phần tử được lấy từ luồng này khớp với vị từ đã cho.

Thí dụ

import java.util.stream.Stream;

public class Tester {
   public static void main(String[] args) {
      Stream.of("a","b","c","","e","f").takeWhile(s->!s.isEmpty())
         .forEach(System.out::print);		 
   } 
}

Đầu ra

Phương thức takeWhile nhận tất cả các giá trị a, b và c, sau đó khi chuỗi trống, nó sẽ ngừng thực thi.

abc

dropWhile (Giao diện dự đoán)

Cú pháp

default Stream<T> dropWhile(Predicate<? super T> predicate)

Phương thức dropWhile loại bỏ tất cả các giá trị khi bắt đầu cho đến khi vị từ trả về true. Nó trả về, trong trường hợp luồng có thứ tự, một luồng bao gồm các phần tử còn lại của luồng này sau khi bỏ tiền tố dài nhất của các phần tử khớp với vị từ đã cho.

Thí dụ

import java.util.stream.Stream;

public class Tester {
   public static void main(String[] args) {
      Stream.of("a","b","c","","e","f").dropWhile(s-> !s.isEmpty())
      .forEach(System.out::print);
      System.out.println();
      Stream.of("a","b","c","","e","","f").dropWhile(s-> !s.isEmpty())
      .forEach(System.out::print);
   } 
}

Đầu ra

Phương thức dropWhile giảm giá trị a, b và c, sau đó khi chuỗi trống, nó sẽ nhận tất cả các giá trị.

ef
ef

lặp lại

Cú pháp

static <T> Stream<T> iterate(T seed, Predicate<? super T> hasNext, UnaryOperator<T> next)

phương thức lặp hiện có vị từ hasNext làm tham số dừng vòng lặp khi vị từ hasNext trả về false.

Thí dụ

import java.util.stream.IntStream;

public class Tester {
   public static void main(String[] args) {
      IntStream.iterate(3, x -> x < 10, x -> x+ 3).forEach(System.out::println);
   } 
}

Đầu ra

3
6
9

ofNullable

Cú pháp

static <T> Stream<T> ofNullable(T t)

Phương thức ofNullable được giới thiệu để ngăn NullPointerExceptions và tránh kiểm tra null cho các luồng. Phương thức này trả về một Luồng tuần tự chứa một phần tử duy nhất, nếu không phải null, nếu không thì trả về một Luồng trống.

Thí dụ

import java.util.stream.Stream;

public class Tester {
   public static void main(String[] args) {
      long count = Stream.ofNullable(100).count();
      System.out.println(count);
  
      count = Stream.ofNullable(null).count();
      System.out.println(count);
   } 
}

Đầu ra

1
0

Câu lệnh try-with-resources là một câu lệnh try với một hoặc nhiều tài nguyên được khai báo hợp lệ. Ở đây tài nguyên là một đối tượng nên được đóng lại khi nó không được yêu cầu nữa. Câu lệnh try-with-resources đảm bảo rằng mỗi tài nguyên được đóng sau khi yêu cầu kết thúc. Bất kỳ đối tượng nào triển khai java.lang.AutoClosable hoặc java.io.Closable, giao diện đều có thể được sử dụng làm tài nguyên.

Trước Java 9, các tài nguyên phải được khai báo trước câu lệnh try hoặc bên trong try như minh họa bên dưới trong ví dụ đã cho. Trong ví dụ này, chúng tôi sẽ sử dụng BufferedReader làm tài nguyên để đọc một chuỗi và sau đó BufferedReader sẽ được đóng lại.

Tester.java

import java.io.BufferedReader;
import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;

public class Tester {
   public static void main(String[] args) throws IOException {
      System.out.println(readData("test"));
   } 

   static String readData(String message) throws IOException {
      Reader inputString = new StringReader(message);
      BufferedReader br = new BufferedReader(inputString);
      try (BufferedReader br1 = br) {
         return br1.readLine();
      }
   }
}

Đầu ra

test

Ở đây chúng ta cần khai báo một tài nguyên br1 trong trạng thái thử và sau đó sử dụng nó. Trong Java9, chúng ta không cần khai báo br1 nữa và chương trình sau sẽ cho kết quả tương tự.

Tester.java

import java.io.BufferedReader;
import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;

public class Tester {
   public static void main(String[] args) throws IOException {
      System.out.println(readData("test"));
   } 

   static String readData(String message) throws IOException {
      Reader inputString = new StringReader(message);
      BufferedReader br = new BufferedReader(inputString);
      try (br) {
         return br.readLine();
      }
   }
}

Đầu ra

test

Chú thích @Deprecated đã được giới thiệu trong phiên bản java 5. Phần tử chương trình được chú thích bằng @Deprecated có nghĩa là nó không nên được sử dụng vì bất kỳ lý do nào sau đây:

  • Việc sử dụng nó có thể dẫn đến lỗi.
  • Nó có thể không tương thích trong phiên bản tương lai.
  • Nó có thể bị xóa trong phiên bản tương lai.
  • Một giải pháp thay thế tốt hơn và hiệu quả hơn đã thay thế nó.

Trình biên dịch tạo ra cảnh báo bất cứ khi nào một phần tử không dùng nữa được sử dụng. Với Java 9, hai cải tiến mới được thực hiện cho chú thích @Deprecated.

  • forRemoval- Cho biết liệu phần tử được chú thích có bị xóa trong phiên bản trong tương lai hay không. Giá trị mặc định là sai.

  • since- Trả về phiên bản mà phần tử chú thích không được dùng nữa. Giá trị mặc định là chuỗi trống.

Không được chấp nhận với kể từ

Ví dụ sau về lớp Boolean javadoc trên Java 9 minh họa việc sử dụng thuộc tính since trên chú thích @Deprecated.

Lớp Boolean

Không được chấp nhận với forRemoval

Ví dụ sau về javadoc lớp Hệ thống trên Java 9 minh họa việc sử dụng thuộc tính forRemoval trên chú thích @Deprecated.

Lớp hệ thống

Toán tử Diamond đã được giới thiệu trong java 7 để làm cho mã dễ đọc hơn nhưng nó không thể được sử dụng với các lớp ẩn danh bên trong. Trong java 9, nó cũng có thể được sử dụng với lớp ẩn danh để đơn giản hóa mã và cải thiện khả năng đọc. Hãy xem xét đoạn mã sau trước Java 9.

Tester.java

public class Tester {
   public static void main(String[] args) {
         Handler<Integer> intHandler = new Handler<Integer>(1) {
         
         @Override
         public void handle() {
            System.out.println(content);
         }
      };

      intHandler.handle();
      Handler<? extends Number> intHandler1 = new Handler<Number>(2) {
         
         @Override
         public void handle() {
            System.out.println(content);
         }
      };

      intHandler1.handle();
      Handler<?> handler = new Handler<Object>("test") {
         
         @Override
         public void handle() {
            System.out.println(content);
         }
      };

      handler.handle();    
   }  
}

abstract class Handler<T> {
   public T content;

   public Handler(T content) {
      this.content = content; 
   }
   
   abstract void handle();
}

Đầu ra

1
2
Test

Với Java 9, chúng ta có thể sử dụng toán tử <> với lớp ẩn danh như hình bên dưới.

Tester.java

public class Tester {
   public static void main(String[] args) {
         Handler<Integer> intHandler = new Handler<>(1) {
         
         @Override
         public void handle() {
            System.out.println(content);
         }
      };

      intHandler.handle();
      Handler<? extends Number> intHandler1 = new Handler<>(2) {
         
         @Override
         public void handle() {
            System.out.println(content);
         }
      };

      intHandler1.handle();
      Handler<?> handler = new Handler<>("test") {
         
         @Override
         public void handle() {
            System.out.println(content);
         }
      };

      handler.handle();    
   }  
}

abstract class Handler<T> {
   public T content;

   public Handler(T content) {
      this.content = content; 
   }
   
   abstract void handle();
}

Đầu ra

1
2
Test

Lớp tùy chọn đã được giới thiệu trong Java 8 để tránh kiểm tra rỗng và các vấn đề NullPointerException. Trong java 9, ba phương pháp mới được thêm vào để cải thiện chức năng của nó.

  • stream()
  • ifPresentOrElse()
  • or()

phương thức stream ()

Cú pháp

public Stream<T> stream()

Nếu một giá trị có mặt, nó trả về một Luồng tuần tự chỉ chứa giá trị đó, nếu không sẽ trả về một Luồng trống.

Thí dụ

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

public class Tester {
public static void main(String[] args) {
   List<Optional<String>> list = Arrays.asList (
      Optional.empty(), 
      Optional.of("A"), 
      Optional.empty(), 
      Optional.of("B"));

   //filter the list based to print non-empty values
  
   //if optional is non-empty, get the value in stream, otherwise return empty
   List<String> filteredList = list.stream()
      .flatMap(o -> o.isPresent() ? Stream.of(o.get()) : Stream.empty())
      .collect(Collectors.toList());

   //Optional::stream method will return a stream of either one 
   //or zero element if data is present or not.
   List<String> filteredListJava9 = list.stream()
      .flatMap(Optional::stream)
      .collect(Collectors.toList());

      System.out.println(filteredList);
      System.out.println(filteredListJava9);
   }  
}

Đầu ra

[A, B]
[A, B]

phương thức ifPresentOrElse ()

Cú pháp

public void ifPresentOrElse(Consumer<? super T> action, Runnable emptyAction)

Nếu có giá trị, hãy thực hiện hành động đã cho với giá trị, nếu không thì thực hiện hành động dựa trên sản phẩm trống đã cho.

Thí dụ

import java.util.Optional;

public class Tester {
   public static void main(String[] args) {
      Optional<Integer> optional = Optional.of(1);

      optional.ifPresentOrElse( x -> System.out.println("Value: " + x),() -> 
         System.out.println("Not Present."));

      optional = Optional.empty();

      optional.ifPresentOrElse( x -> System.out.println("Value: " + x),() -> 
         System.out.println("Not Present."));
   }  
}

Đầu ra

Value: 1
Not Present.

hoặc () phương thức

Cú pháp

public Optional<T> or(Supplier<? extends Optional<? extends T>> supplier)

Nếu có giá trị, trả về Tùy chọn mô tả giá trị, nếu không trả về Tùy chọn do hàm cung cấp tạo ra.

Thí dụ

import java.util.Optional;
import java.util.function.Supplier;

public class Tester {
   public static void main(String[] args) {
      Optional<String> optional1 = Optional.of("Mahesh");

      Supplier<Optional<String>> supplierString = () -> Optional.of("Not Present");

      optional1 = optional1.or( supplierString);
  
      optional1.ifPresent( x -> System.out.println("Value: " + x));
    
      optional1 = Optional.empty();    

      optional1 = optional1.or( supplierString);
  
      optional1.ifPresent( x -> System.out.println("Value: " + x));  
   }  
}

Đầu ra

Value: Mahesh
Value: Not Present

Với Java 9, một API hình ảnh đa độ phân giải mới đã được giới thiệu, hỗ trợ nhiều hình ảnh với các biến thể độ phân giải khác nhau. API này cho phép một tập hợp các hình ảnh có độ phân giải khác nhau được sử dụng như một hình ảnh đa độ phân giải. Sau đây là các thao tác chính của hình ảnh đa độ phân giải.

  • Image getResolutionVariant(double destImageWidth, double destImageHeight) - Nhận một hình ảnh cụ thể là biến thể tốt nhất để đại diện cho hình ảnh logic này ở kích thước được chỉ định.

  • List<Image> getResolutionVariants() - Nhận danh sách có thể đọc được của tất cả các biến thể độ phân giải.

Thí dụ

import java.io.IOException;
import java.net.URL;
import java.net.MalformedURLException;
import java.util.ArrayList;
import java.util.List;
import java.awt.Image;
import java.awt.image.MultiResolutionImage;
import java.awt.image.BaseMultiResolutionImage;

import javax.imageio.ImageIO;

public class Tester {
   public static void main(String[] args) throws IOException, MalformedURLException {

      List<String> imgUrls = List.of("http://www.tutorialspoint.com/java9/images/logo.png",
         "http://www.tutorialspoint.com/java9/images/mini_logo.png",
         "http://www.tutorialspoint.com/java9/images/large_logo.png");

      List<Image> images = new ArrayList<Image>();

      for (String url : imgUrls) {
         images.add(ImageIO.read(new URL(url)));
      }

      // read all images into one multiresolution image
      MultiResolutionImage multiResolutionImage = 
         new BaseMultiResolutionImage(images.toArray(new Image[0]));

      // get all variants of images
      List<Image> variants = multiResolutionImage.getResolutionVariants();

      System.out.println("Total number of images: " + variants.size());

      for (Image img : variants) {
         System.out.println(img);
      }

      // get a resolution-specific image variant for each indicated size
      Image variant1 = multiResolutionImage.getResolutionVariant(156, 45);
      System.out.printf("\nImage for destination[%d,%d]: [%d,%d]", 
         156, 45, variant1.getWidth(null), variant1.getHeight(null));

      Image variant2 = multiResolutionImage.getResolutionVariant(311, 89);
      System.out.printf("\nImage for destination[%d,%d]: [%d,%d]", 311, 89, 
         variant2.getWidth(null), variant2.getHeight(null));

      Image variant3 = multiResolutionImage.getResolutionVariant(622, 178);
      System.out.printf("\nImage for destination[%d,%d]: [%d,%d]", 622, 178, 
         variant3.getWidth(null), variant3.getHeight(null));

      Image variant4 = multiResolutionImage.getResolutionVariant(300, 300);
      System.out.printf("\nImage for destination[%d,%d]: [%d,%d]", 300, 300, 
         variant4.getWidth(null), variant4.getHeight(null));
   }  
}

Đầu ra

Total number of images: 3
BufferedImage@7ce6a65d: type = 6 ColorModel: #pixelBits = 32 numComponents = 4 
color space =java.awt.color.ICC_ColorSpace@548ad73b transparency = 3 
has alpha = true isAlphaPre = false ByteInterleavedRaster: width =311 
height = 89 #numDataElements 4 dataOff[0] = 3

BufferedImage@4c762604: type = 6 ColorModel: #pixelBits = 32 numComponents = 4 
color space =java.awt.color.ICC_ColorSpace@548ad73b transparency = 3 
has alpha = true isAlphaPre = false ByteInterleavedRaster: width =156 
height = 45 #numDataElements 4 dataOff[0] = 3

BufferedImage@2641e737: type = 6 ColorModel: #pixelBits = 32 numComponents = 4 
color space =java.awt.color.ICC_ColorSpace@548ad73b transparency = 3 
has alpha = true isAlphaPre = false ByteInterleavedRaster: width =622 
height = 178 #numDataElements 4 dataOff[0] = 3

Image for destination[156,45]: [311,89]
Image for destination[311,89]: [311,89]
Image for destination[622,178]: [622,178]
Image for destination[300,300]: [622,178]

Lớp CompletableFuture được giới thiệu trong Java 8 để đại diện cho Tương lai có thể được hoàn thành bằng cách đặt giá trị và trạng thái rõ ràng của nó. Nó có thể được sử dụng như java.util.concurrent.CompletionStage. Nó hỗ trợ các chức năng và hành động phụ thuộc được kích hoạt khi hoàn thành trong tương lai. Trong java 9, API CompletableFuture đã được cải tiến hơn nữa. Sau đây là những thay đổi có liên quan được thực hiện đối với API.

  • Hỗ trợ cho sự chậm trễ và hết thời gian.
  • Cải thiện hỗ trợ cho phân lớp.
  • Đã thêm các phương pháp nhà máy mới.

Hỗ trợ cho sự chậm trễ và hết thời gian

public CompletableFuture<T> completeOnTimeout(T value, long timeout, TimeUnit unit)

Phương thức này hoàn thành CompletableFuture này với giá trị đã cho nếu không hoàn thành trước thời gian chờ đã cho.

public CompletableFuture<T> orTimeout(long timeout, TimeUnit unit)

Phương thức này đặc biệt hoàn thành CompletableFuture này với một TimeoutException nếu không được hoàn thành trước thời gian chờ đã cho.

Cải thiện hỗ trợ cho phân lớp con

public Executor defaultExecutor()

Nó trả về Executor mặc định được sử dụng cho các phương thức không đồng bộ không chỉ định Executor. Phương thức này có thể được ghi đè trong các lớp con để trả về một Người thực thi để cung cấp tối thiểu một luồng độc lập.

public <U> CompletableFuture<U> newIncompleteFuture()

Trả về một CompletableFuture chưa hoàn thành mới của loại được trả về bởi một phương thức CompletionStage. Các lớp con của lớp CompletableFuture nên ghi đè phương thức này để trả về một thể hiện của cùng một lớp với lớp CompletableFuture này. Việc triển khai mặc định trả về một thể hiện của lớp CompletableFuture.

Phương pháp nhà máy mới

public static <U> CompletableFuture<U> completedFuture(U value)

Phương thức factory này trả về một CompletableFuture mới đã được hoàn thành với giá trị đã cho.

public static <U> CompletionStage<U> completedStage(U value)

Phương thức gốc này trả về một CompletionStage mới đã được hoàn thành với giá trị đã cho và chỉ hỗ trợ những phương thức có trong giao diện CompletionStage.

public static <U> CompletionStage<U> failedStage(Throwable ex)

Phương thức gốc này trả về một CompletionStage mới đã được hoàn thành đặc biệt với ngoại lệ đã cho và chỉ hỗ trợ những phương thức có trong giao diện CompletionStage.

Ngoài các tính năng đã đề cập, với Java 9, rất nhiều cải tiến được thực hiện cho nền tảng JDK. Một số trong số họ được liệt kê dưới đây.

  • Cải tiến GC (Bộ thu gom rác)
  • API Stack-Walking
  • Lọc dữ liệu tuần tự hóa đến
  • Ngừng sử dụng API Applet
  • Chỉ định kết nối chuỗi
  • Xử lý phương pháp nâng cao
  • Dịch vụ và API ghi nhật ký nền tảng Java
  • Chuỗi nhỏ gọn
  • API phân tích cú pháp cho Nashorn