Reading Time: 10 minutes

Hôm nay, chúng ta sẽ cùng đi sâu vào một bản phát hành quan trọng đã thay đổi cách chúng ta viết code Java : Java 9.

kham-pha-java-9

Đây không chỉ là một bản cập nhật thông thường, mà là một bước nhảy vọt, mang đến rất nhiều tính năng mới mẻ và cải tiến đáng kể cho các nhà phát triển. Từ việc nâng cao năng suất với một công cụ tương tác mạnh mẽ đến việc định hình lại cách chúng ta xây dựng các ứng dụng lớn bằng hệ thống module, Java 9 đã mở ra nhiều hướng đi mới và giải quyết không ít vấn đề tồn đọng.

Các tính năng chính của Java 9

Java 9 đã được phát hành bởi Oracle Corporation vào khoảng cuối tháng 3 năm 2017 (lưu ý: phiên bản Java 10 cũng đã ra mắt sau đó, mang theo nhiều cải tiến hơn nữa). Dưới đây là một số tính năng quan trọng nhất mà bản cập nhật này mang lại:

  1. REPL trong Java 9 (JShell)
  2. Phương thức Factory cho List, Set, Map và Map.Entry bất biến
  3. Phương thức private trong Interface
  4. Hệ thống Module của Java 9 (Java Module System)
  5. Cải tiến API xử lý tiến trình (Process API)
  6. Cải tiến Try-With-Resources
  7. Cải tiến API CompletableFuture
  8. Reactive Streams
  9. Toán tử Diamond cho lớp ẩn danh (Anonymous Inner Class)
  10. Cải tiến lớp Optional
  11. Cải tiến API Stream
  12. Chú thích @Deprecated được mở rộng
  13. HTTP 2 Client
  14. API hình ảnh đa độ phân giải (Multi-Resolution Image API)
  15. Các tính năng Java 9 khác

Trong bài viết này, tôi sẽ đi sâu thảo luận về các tính năng của Java 9 một cách ngắn gọn kèm theo một số ví dụ minh họa để bạn dễ hình dung.

Java 9 REPL(jshell)

Oracle Corporation đã giới thiệu một công cụ mới mang tên “jshell” trong Java 9. JShell là viết tắt của Java Shell và còn được biết đến với tên gọi REPL (Read Evaluate Print Loop – Đọc, Đánh giá, In, Lặp lại). Công cụ này cho phép chúng ta thực thi và kiểm tra bất kỳ cấu trúc Java nào như class, interface, enum, object, hay các câu lệnh một cách cực kỳ dễ dàng và nhanh chóng. Điều này rất hữu ích cho việc thử nghiệm các đoạn code nhỏ mà không cần phải biên dịch và chạy một file Java đầy đủ.

G:\\\\>jshell
|  Welcome to JShell -- Version9-ea
|  For an introduction type: /help intro

jshell> int a = 10
a ==> 10

jshell> System.out.println("a value = " + a )
a value = 10

Factory methods cho immutable list, set, map và map.entry

Java 9 đã giới thiệu một số phương thức factory tiện lợi để tạo các đối tượng Immutable List, Set, MapMap.Entry. Các phương thức tiện ích này được sử dụng để tạo các đối tượng Collection rỗng hoặc không rỗng một cách hiệu quả hơn.

Trong Java SE 8 và các phiên bản trước, chúng ta có thể sử dụng các phương thức tiện ích của lớp Collections như unmodifiableXXX để tạo các đối tượng Immutable Collection. Ví dụ, nếu chúng ta muốn tạo một Immutable List, chúng ta có thể sử dụng phương thức Collections.unmodifiableList. Tuy nhiên, các phương thức Collections.unmodifiableXXX này thường khá dài dòng và tẻ nhạt.

Để khắc phục những thiếu sót đó, Oracle Corporation đã thêm một số phương thức tiện ích vào các interface List, SetMap. Các interface ListSet có các phương thức of() để tạo các đối tượng Immutable List hoặc Set rỗng hoặc không rỗng như sau:

Ví dụ list rỗng

List immutableList = List.of();

Ví dụ list không rỗng

List immutableList = List.of("one","two","three");

Map có hai bộ phương thức: of()ofEntries() để tạo một đối tượng Immutable Map và một đối tượng Immutable Map.Entry tương ứng.

Ví dụ map rỗng

jshell> Map emptyImmutableMap = Map.of()
emptyImmutableMap ==> {}

Ví dụ map không rỗng

jshell> Map nonemptyImmutableMap = Map.of(1, "one", 2, "two", 3, "three")
nonemptyImmutableMap ==> {2=two, 3=three, 1=one}

Private methods trong interfaces

Trong Java 8, chúng ta có thể cung cấp cài đặt phương thức trong các Interface bằng cách sử dụng DefaultStatic methods. Tuy nhiên, chúng ta không thể tạo các phương thức private trong Interfaces. Để tránh mã trùng lặp và tăng khả năng tái sử dụng, Oracle Corporation đã giới thiệu private methods trong Java SE 9 Interfaces.

Từ Java SE 9 trở đi, chúng ta có thể viết các phương thức privateprivate static trong một interface bằng cách sử dụng từ khóa ‘private’. Các phương thức private này hoạt động tương tự như các phương thức private trong class, không có sự khác biệt nào giữa chúng.

public interface Card{

  private Long createCardID(){
    // Cài đặt phương thức ở đây.
  }

  private static void displayCardDetails(){
    // Cài đặt phương thức ở đây.
  }

}

Java 9 module system

Một trong những thay đổi lớn nhất hay tính năng đột phá của Java 9 chính là hệ thống Module. Oracle Corporation đã giới thiệu các tính năng sau đây như một phần của Jigsaw Project:

  • Modular JDK
  • Modular Java Source Code
  • Modular Run-time Images
  • Encapsulate Java Internal APIs
  • Java Platform Module System

Trước các phiên bản Java SE 9, chúng ta thường sử dụng các tệp Jar nguyên khối (Monolithic Jars) để phát triển các ứng dụng dựa trên Java . Kiến trúc này có rất nhiều hạn chế và nhược điểm. Để tránh tất cả những thiếu sót này, Java SE 9 đã ra đời với hệ thống Module. JDK9 đi kèm với92 module (con số này có thể thay đổi trong bản phát hành cuối cùng). Chúng ta có thể sử dụng các JDK Modules và cũng có thể tạo các module của riêng mình như sau:

Ví dụ module đơn giản

module com.foo.bar { }

Ở đây, chúng ta sử dụng từ khóa ‘module’ để tạo một module đơn giản. Mỗi module có một tên, mã liên quan và các tài nguyên khác.

Cải tiến Process API

Java SE 9 đi kèm với một số cải tiến trong Process API. Họ đã thêm một vài lớp và phương thức mới để dễ dàng kiểm soát và quản lý các tiến trình của hệ điều hành. Hai giao diện mới trong Process API:

  • Java .lang.processhandle
  • Java .lang.processhandle.info

ví dụ process api

ProcessHandle currentProcess = ProcessHandle.current();
 System.out.println("Current Process Id: = " + currentProcess.getPid());

Cải tiến Try-With-Resources

Chúng ta đều biết, Java SE 7 đã giới thiệu một cấu trúc xử lý ngoại lệ mới: Try-With-Resources để quản lý tài nguyên tự động. Mục tiêu chính của câu lệnh mới này là “Quản lý tài nguyên tự động tốt hơn”. Java SE 9 tiếp tục cung cấp một số cải tiến cho câu lệnh này để tránh sự dài dòng hơn nữa và cải thiện khả năng đọc.

Ví dụ Java SE 7

void testARM_Before_Java 9() throws IOException{
 BufferedReader reader1 = new BufferedReader(new FileReader("journaldev.txt"));
 try (BufferedReader reader2 = reader1) {
   System.out.println(reader2.readLine());
 }
}

Ví dụ Java 9

void testARM_Java 9() throws IOException{
 BufferedReader reader1 = new BufferedReader(new FileReader("journaldev.txt"));
 try (reader1) {
   System.out.println(reader1.readLine());
 }
}

Cải tiến CompletableFuture API

Trong Java SE 9, Oracle Corporation đã cải thiện CompletableFuture API để giải quyết một số vấn đề phát sinh trong Java SE 8. Họ đã thêm hỗ trợ cho các độ trễ và thời gian chờ, một số phương thức tiện ích và khả năng kế thừa tốt hơn.

Executor exe = CompletableFuture.delayedExecutor(50L, TimeUnit.SECONDS);

Ở đây delayedExecutor() là một phương thức tiện ích tĩnh được sử dụng để trả về một Executor mới mà thực hiện một tác vụ đến trình thực thi mặc định sau một độ trễ nhất định.

Reactive Streams

Ngày nay, Reactive Programming đã trở nên rất phổ biến trong việc phát triển ứng dụng để đạt được những lợi ích đáng kể. Các Framework như Scala, Play, Akka, v.v. đã tích hợp Reactive Streams và đang thu được nhiều lợi ích. Oracle Corporation cũng đang giới thiệu Reactive Streams API mới trong Java SE 9.

Java SE 9 Reactive Streams API là một Framework Publish/Subscribe để triển khai các ứng dụng Bất đồng bộ (Asynchronous), Có khả năng mở rộng (Scalable) và Song song (Parallel) một cách rất dễ dàng bằng ngôn ngữ Java . Java SE 9 đã giới thiệu các API sau đây để phát triển Reactive Streams trong các ứng dụng dựa trên Java :

  • Java .util.concurrent.flow
  • Java .util.concurrent.flow.publisher
  • Java .util.concurrent.flow.subscriber
  • Java .util.concurrent.flow.processor

Diamond Operato cho Anonymous Inner Class

Chúng ta biết, Java SE 7 đã giới thiệu một tính năng mới: Diamond Operator để tránh mã trùng lặp và sự dài dòng, cải thiện khả năng đọc. Tuy nhiên, trong Java SE 8, Oracle Corporation (Nhà phát triển Thư viện Java ) đã phát hiện ra một số hạn chế trong việc sử dụng Diamond Operator với Anonymous Inner Class. Họ đã khắc phục những vấn đề đó và sẽ phát hành chúng như một phần của Java 9.

public List getEmployee(String empid){
     // Code để lấy thông tin chi tiết nhân viên từ Data Store
     return new List(emp){ };
  }

Ở đây chúng ta chỉ sử dụng “List” mà không chỉ định tham số kiểu.

Cải tiến Optional Class

Trong Java SE 9, Oracle Corporation đã thêm một số phương thức mới hữu ích vào lớp Java .util.Optional. Ở đây tôi sẽ thảo luận về một trong những phương thức đó với một ví dụ đơn giản: phương thức stream().

Nếu một giá trị có mặt trong đối tượng Optional đã cho, phương thức stream() này sẽ trả về một Stream tuần tự với giá trị đó. Ngược lại, nó trả về một Stream rỗng. Họ đã thêm phương thức stream() để làm việc với các đối tượng Optional một cách lười biếng (lazily) như sau:

Stream<Optional> emp = getEmployee(id)
Stream empStream = emp.flatMap(Optional::stream)

Ở đây phương thức Optional.stream() được sử dụng để chuyển đổi một Stream của Optional của đối tượng Employee thành một Stream của Employee để chúng ta có thể làm việc với kết quả này một cách lười biếng trong mã kết quả. Để hiểu rõ hơn về tính năng này với nhiều ví dụ hơn và tìm hiểu các phương thức mới khác được thêm vào lớp Optional.

Cải tiến Stream API

Trong Java SE 9, Oracle Corporation đã thêm bốn phương thức mới hữu ích vào interface Java .util.Stream. Vì Stream là một interface, tất cả các phương thức được cài đặt mới đó đều là default methods. Hai trong số đó rất quan trọng: các phương thức dropWhiletakeWhile.

Nếu bạn quen thuộc với ngôn ngữ Scala hoặc bất kỳ ngôn ngữ lập trình hàm nào, bạn chắc chắn sẽ biết về các phương thức này. Chúng rất hữu ích trong việc viết mã theo phong cách hàm. Hãy cùng thảo luận về phương thức tiện ích takeWhile ở đây.

takeWhile() này nhận một predicate làm đối số và trả về một Stream của tập con các giá trị của Stream đã cho cho đến khi Predicate đó trả về false lần đầu tiên. Nếu giá trị đầu tiên KHÔNG thỏa mãn Predicate đó, nó chỉ trả về một Stream rỗng.

jshell> Stream.of(1,2,3,4,5,6,7,8,9,10).takeWhile(i -> i < 5 )
                 .forEach(System.out::println);
1
2
3
4

Để đọc thêm về các phương thức takeWhiledropWhile cũng như các phương thức mới khác, bạn có thể tham khảo hướng dẫn chi tiết tại: Java SE 9: stream api improvements.

Enhanced @Deprecated annotation

Trong Java SE 8 và các phiên bản trước, @Deprecated annotation chỉ là một interface đánh dấu (Marker interface) không có bất kỳ phương thức nào. Nó được sử dụng để đánh dấu một API Java là class, field, method, interface, constructor, enum, v.v. đã lỗi thời.

Trong Java SE 9, Oracle Corporation đã cải tiến @Deprecated annotation để cung cấp nhiều thông tin hơn về API đã lỗi thời và cũng cung cấp một công cụ để phân tích việc sử dụng tĩnh của các API lỗi thời trong một ứng dụng. Họ đã thêm hai phương thức vào interface Deprecated này: forRemovalsince để cung cấp thông tin này.

Http 2 Client

Trong Java SE 9, Oracle Corporation đã phát hành New HTTP 2 Client API để hỗ trợ giao thức HTTP/2 và các tính năng WebSocket. Vì Existing hoặc Legacy HTTP Client API có nhiều vấn đề (như chỉ hỗ trợ giao thức HTTP/1.1 và không hỗ trợ giao thức HTTP/2 và WebSocket, chỉ hoạt động ở chế độ Blocking và nhiều vấn đề về hiệu suất), họ đã thay thế API HttpURLConnection này bằng HTTP Client mới.

Họ đã giới thiệu một New HTTP 2 Client API trong gói “Java .net.http”. Nó hỗ trợ cả giao thức HTTP/1.1 và HTTP/2. Nó hỗ trợ cả Chế độ Đồng bộ (Blocking Mode) và Chế độ Bất đồng bộ (Asynchronous Modes). Nó hỗ trợ Chế độ Bất đồng bộ bằng cách sử dụng WebSocket API. Chúng ta có thể xem API mới này tại đường dẫn https://download.Java .net/Java /jdk9/docs/api/Java /net/http/package-summary.html

Ví dụ http 2 client

jshell> import Java .net.http.*

jshell> import static Java .net.http.HttpRequest.*

jshell> import static Java .net.http.HttpResponse.*

jshell> URI uri = new URI("<https://rams4Java .blogspot.co.uk/2016/05/Java -news.html>")
uri ==> <https://rams4Java .blogspot.co.uk/2016/05/Java -news.html>

jshell> HttpResponse response = HttpRequest.create(uri).body(noBody()).GET().response()
response ==> Java .net.http.HttpResponseImpl@79efed2d

jshell> System.out.println("Response was " + response.body(asString()))

Vui lòng tham khảo hướng dẫn chi tiết tại: Java SE 9: http 2 client để hiểu rõ về giao thức HTTP/2 & WebSocket, lợi ích của API mới và nhược điểm của API cũ kèm theo các ví dụ hữu ích.

Multi-Resolution Image API

Trong Java SE 9, Oracle Corporation đã giới thiệu một New Multi-Resolution Image API. Interface quan trọng trong API này là MultiResolutionImage. Nó có sẵn trong gói Java .awt.image. MultiResolutionImage đóng gói một tập hợp các hình ảnh với các chiều cao và chiều rộng khác nhau (tức là các độ phân giải khác nhau) và cho phép chúng ta truy vấn chúng theo yêu cầu của mình.

Các tính năng khác của Java 9

Trong phần này, tôi sẽ chỉ liệt kê một số tính năng mới khác của Java SE 9. Tôi không nói rằng đây là những tính năng kém quan trọng. Chúng cũng quan trọng và hữu ích để hiểu rõ với một số ví dụ hữu ích. Hiện tại, tôi chưa có đủ thông tin về các tính năng này để đi sâu chi tiết. Đó là lý do tại sao tôi sẽ liệt kê chúng ở đây để bạn có cái nhìn tổng quan. Tôi sẽ chọn từng tính năng này và cập nhật chúng vào các phần trên với một cuộc thảo luận ngắn gọn và ví dụ, và cuối cùng viết một hướng dẫn riêng sau.

  • GC (Garbage Collector) Improvements
  • Stack-Walking API
  • Filter Incoming Serialization Data
  • Deprecate the Applet API
  • Indify String Concatenation
  • Enhanced Method Handles
  • Java Platform Logging API and Service
  • Compact Strings
  • Parser API for Nashorn
  • Javadoc Search
  • HTML5 Javadoc

Kết luận

Qua bài viết này, chúng ta đã cùng nhau khám phá những tính năng chính mà Java 9 mang lại. Từ JShell giúp thử nghiệm mã nhanh chóng, các Factory Methods cho Collections bất biến giúp code ngắn gọn và an toàn hơn, đến việc cho phép Private Methods trong Interface cải thiện khả năng tái sử dụng mã. Đặc biệt, Java Platform Module System (Project Jigsaw) là một bước đột phá, giúp ứng dụng Java trở nên modular, dễ quản lý, bảo mật và tối ưu hơn về kích thước. Các cải tiến về Process API, Try-With-Resources, CompletableFuture, Reactive Streams, Stream API, cùng với HTTP/2 Client mới, đều góp phần nâng cao hiệu suất và khả năng phát triển ứng dụng hiện đại.

Việc nắm vững các tính năng này sẽ giúp bạn viết mã Java sạch hơn, hiệu quả hơn và bắt kịp với xu hướng phát triển phần mềm hiện đại.

0 Bình luận

Đăng nhập để thảo luận

Chuyên mục Hướng dẫn

Tổng hợp các bài viết hướng dẫn, nghiên cứu và phân tích chi tiết về kỹ thuật, các xu hướng công nghệ mới nhất dành cho lập trình viên.

Đăng ký nhận bản tin của chúng tôi

Hãy trở thành người nhận được các nội dung hữu ích của CyStack sớm nhất

Xem chính sách của chúng tôi Chính sách bảo mật.

Đăng ký nhận Newsletter

Nhận các nội dung hữu ích mới nhất