Tổng quan các tính năng mới của Java 14 & 15
Java 14
JDK 14 được phát hành vào ngày 17 tháng 3 năm 2020, đây là một phiên bản non-LTS.
Bài viết này sẽ chọn một số tính năng mới quan trọng để giới thiệu chi tiết:
- JEP 305: Pattern Matching for instanceof (instanceof pattern matching, preview)
- JEP 358: Helpful NullPointerExceptions (thông báo chính xác về NullPointerException)
- JEP 361: Switch Expressions (Standard) (switch expressions, phiên bản chính thức)
- JEP 359: Records (Preview) (từ khóa record, tính năng preview)
- JEP 368: Text Blocks (Second Preview) (text blocks, preview lần thứ hai)
- JEP 363: Remove the CMS Garbage Collector (loại bỏ CMS garbage collector)
Hình dưới đây thể hiện số lượng tính năng mới và thời điểm cập nhật của từng phiên bản từ JDK 8 đến JDK 25:

JEP 305: Pattern Matching for instanceof (instanceof pattern matching, preview)
Java 14 tiếp tục cung cấp instanceof pattern matching dưới dạng một tính năng preview. Đây là tính năng được Java 14 giới thiệu (JEP 305).
Tính năng này cho phép thực hiện chuyển đổi kiểu đồng thời với việc kiểm tra instanceof, tránh phải ép kiểu tường minh. Lưu ý: instanceof pattern matching là preview lần đầu trong Java 14 (JEP 305), preview lần thứ hai trong Java 15 (JEP 375), và trở thành tính năng chính thức trong Java 16 (JEP 394).
JEP 358: Helpful NullPointerExceptions (thông báo chính xác về NullPointerException)
Bằng cách thêm -XX:+ShowCodeDetailsInExceptionMessages vào tham số JVM, có thể nhận được thông tin chi tiết hơn về lời gọi gây ra NullPointerException, từ đó định vị và giải quyết vấn đề nhanh hơn.
a.b.c.i = 99; // Giả sử đoạn code này sẽ xảy ra null pointerTrước Java 14:
Exception in thread "main" java.lang.NullPointerException
at NullPointerExample.main(NullPointerExample.java:5)Sau Java 14:
// Sau khi thêm tham số, exception thông báo rõ ràng thành phần nào là null
Exception in thread "main" java.lang.NullPointerException:
Cannot read field 'c' because 'a.b' is null.
at Prog.main(Prog.java:5)JEP 361: Switch Expressions (switch expressions, phiên bản chính thức)
switch (được Java 12 giới thiệu dưới dạng tính năng preview) trở thành tính năng chính thức trong Java 14, không cần thêm tham số để bật và có thể sử dụng trực tiếp trong JDK 14.
Java 12 đưa vào switch expressions các block thực thi có cú pháp tương tự lambda sau khi điều kiện khớp thành công, không cần viết thêm break; Java 13 cung cấp yield để trả về giá trị trong block.
String result = switch (day) {
case "M", "W", "F" -> "MWF";
case "T", "TH", "S" -> "TTS";
default -> {
if(day.isEmpty())
yield "Please insert a valid day.";
else
yield "Looks like a Sunday.";
}
};
System.out.println(result);JEP 359: Records (record class, preview)
Từ khóa record có thể đơn giản hóa cách định nghĩa data class (một Java class không thể thay đổi sau khi được khởi tạo), dùng record thay cho class để định nghĩa class, chỉ cần khai báo các thuộc tính là có thể nhận được các accessor của thuộc tính cùng các method toString(), hashCode(), equals().
Cách này tương tự việc dùng class để định nghĩa class, đồng thời sử dụng plugin lombok và thêm các annotation @Getter,@ToString,@EqualsAndHashCode.
/**
* Class này có hai đặc điểm
* 1. Tất cả thuộc tính thành viên đều là final
* 2. Toàn bộ method gồm constructor và accessor của hai thuộc tính thành viên (tổng cộng ba method)
* Vì vậy class này rất phù hợp để khai báo bằng record
*/
final class Rectangle implements Shape {
final double length;
final double width;
public Rectangle(double length, double width) {
this.length = length;
this.width = width;
}
double length() { return length; }
double width() { return width; }
}
/**
* 1. Class được khai báo bằng record sẽ tự động có ba method trong class trên
* 2. Ngoài ra còn có thêm các method equals(), hashCode() và toString()
* 3. Method toString bao gồm dạng biểu diễn chuỗi và tên của tất cả thuộc tính thành viên
*/
record Rectangle(float length, float width) { }JEP 368: Text Blocks (text blocks, preview lần thứ hai)
Trong Java 14, text blocks vẫn là tính năng preview, nhưng đã bổ sung hai escape character mới:
\: biểu thị cuối dòng, không thêm line break\s: biểu thị một khoảng trắng đơn
String str = "Nơi lòng hướng đến, bước chân mộc mạc đi về, đời như quán trọ, một cọng lau cũng đủ vượt qua.";
String str2 = """
Nơi lòng hướng đến, bước chân mộc mạc đi về, \
đời như quán trọ, một cọng lau cũng đủ vượt qua.""";
System.out.println(str2);// Nơi lòng hướng đến, bước chân mộc mạc đi về, đời như quán trọ, một cọng lau cũng đủ vượt qua.
String text = """
java
c++\sphp
""";
System.out.println(text);
// Output:
java
c++ phpCác tính năng khác
- ZGC được giới thiệu từ Java 11, là thuật toán GC thế hệ tiếp theo sau G1. Từ Java 14, ZGC mở rộng hỗ trợ từ nền tảng Linux sang macOS và Windows (theo cảm nhận cá nhân, cuối cùng cũng có thể trải nghiệm hiệu quả của ZGC trong công cụ phát triển hằng ngày, dù thực tế G1 cũng đã đủ dùng)
- JEP 363: Remove the CMS Garbage Collector (loại bỏ CMS garbage collector, hoàn thành sứ mệnh)
- Bổ sung công cụ jpackage. Ngoài việc đóng gói ứng dụng thành jar như tiêu chuẩn, công cụ này còn hỗ trợ các package đặc thù của từng nền tảng, chẳng hạn
debvàrpmtrên Linux,msivàexetrên Windows
Java 15
JDK 15 được phát hành vào ngày 15 tháng 9 năm 2020, đây là một phiên bản non-LTS.
Bài viết này sẽ chọn một số tính năng mới quan trọng để giới thiệu chi tiết:
- JEP 379: Shenandoah: A Low-Pause-Time Garbage Collector (Shenandoah GC, phiên bản chính thức)
- JEP 371: Hidden Classes (hidden classes)
- JEP 378: Text Blocks (Standard) (text blocks, phiên bản chính thức)
- JEP 360: Sealed Classes (Preview) (sealed classes, tính năng preview)
- JEP 339: EdDSA (digital signature algorithm)
Hình dưới đây thể hiện số lượng tính năng mới và thời điểm cập nhật của từng phiên bản từ JDK 8 đến JDK 24:

JEP 379: Shenandoah (Shenandoah GC, phiên bản chính thức)
Shenandoah garbage collector được giới thiệu trong Java 12 dưới dạng tính năng thử nghiệm. Sau nhiều phiên bản cải tiến và hoàn thiện, Shenandoah cuối cùng đã trở thành tính năng chính thức trong Java 15.
Shenandoah là garbage collector có latency thấp do Red Hat chủ trì phát triển, với các mục tiêu chính:
- 99.9% thời gian pause của GC nhỏ hơn 10ms
- Thời gian pause không phụ thuộc vào kích thước heap
- Hỗ trợ heap memory từ vài trăm MB đến vài TB
Khác với G1 và ZGC, Shenandoah sử dụng thuật toán concurrent mark-compact, có thể thực hiện garbage collection mà không dừng các application thread.
Bật Shenandoah GC:
java -XX:+UseShenandoahGC classNameJEP 339: EdDSA (digital signature algorithm)
Bổ sung một digital signature algorithm dựa trên Edwards-Curve Digital Signature Algorithm (EdDSA), có security và performance cao hơn.
Mặc dù performance cao hơn implementation ECDSA hiện có, nó không hoàn toàn thay thế elliptic-curve digital signature algorithm (ECDSA) hiện có trong JDK.
KeyPairGenerator kpg = KeyPairGenerator.getInstance("Ed25519");
KeyPair kp = kpg.generateKeyPair();
byte[] msg = "test_string".getBytes(StandardCharsets.UTF_8);
Signature sig = Signature.getInstance("Ed25519");
sig.initSign(kp.getPrivate());
sig.update(msg);
byte[] s = sig.sign();
String encodedString = Base64.getEncoder().encodeToString(s);
System.out.println(encodedString);Kết quả:
0Hc0lxxASZNvS52WsvnncJOH/mlFhnA8Tc6D/k5DtAX5BSsNVjtPF4R4+yMWXVjrvB2mxVXmChIbki6goFBgAg==JEP 378: Text Blocks (text blocks, phiên bản chính thức)
Trong Java 15, text blocks cuối cùng đã trở thành tính năng chính thức, không còn cần tham số --enable-preview để sử dụng.
Text blocks cung cấp một cách ngắn gọn hơn để định nghĩa chuỗi nhiều dòng, đặc biệt phù hợp với các trường hợp như SQL, JSON, HTML.
JEP 371: Hidden Classes (hidden classes)
Hidden classes được thiết kế cho framework, hỗ trợ các class được tạo động. Các class này không thể được bytecode của class khác sử dụng trực tiếp, chỉ có thể được sử dụng gián tiếp thông qua reflection trong runtime.
Đặc điểm chính:
- Không thể được phát hiện: hidden class không thể được class khác phụ thuộc trực tiếp
- Vòng đời ngắn: thường được unload sau khi sử dụng xong
- Tối ưu performance: cung cấp hỗ trợ performance tốt hơn cho runtime của ngôn ngữ động
Trường hợp sử dụng:
- Runtime của ngôn ngữ động (như JavaScript, Groovy)
- Framework tạo bytecode (như ASM, CGLIB)
- Reflection proxy (như dynamic proxy)
JEP 360: Sealed Classes (sealed classes, preview)
Sealed Classes là một tính năng mới preview trong Java 15.
Trước khi có sealed class, trong Java nếu muốn không cho class khác inherit hoặc sửa đổi một class, có thể dùng từ khóa final để áp dụng cho class. Tuy nhiên, cách này không đủ linh hoạt vì chặn hoàn toàn các khả năng inheritance và sửa đổi của class.
Sealed class có thể giới hạn các class extend hoặc implement chúng, nhờ đó chỉ cho phép các class được chỉ định inherit class này.
// Abstract class Person chỉ cho phép Employee và Manager inheritance.
public abstract sealed class Person
permits Employee, Manager {
//...
}Ngoài ra, mọi class mở rộng sealed class cũng phải khai báo là sealed, non-sealed hoặc final.
public final class Employee extends Person {
}
public non-sealed class Manager extends Person {
}
Nếu các subclass được phép mở rộng và sealed class nằm trong cùng một source code file, sealed class có thể không dùng câu lệnh permits. Java compiler sẽ quét source file và thêm các subclass được phép vào danh sách của sealed class tại thời điểm compile.
JEP 375: Pattern Matching for instanceof (instanceof pattern matching, preview lần thứ hai)
Java 15 tiếp tục cung cấp instanceof pattern matching dưới dạng tính năng preview, không có điều chỉnh lớn, chủ yếu để thu thập thêm phản hồi từ việc sử dụng.
instanceof pattern matching cho phép binding variable đồng thời với kiểm tra kiểu, tránh explicit type cast, giúp code ngắn gọn và an toàn hơn.
Ví dụ:
// Cách viết truyền thống
if (obj instanceof String) {
String str = (String) obj;
System.out.println(str.length());
}
// Cách viết bằng pattern matching
if (obj instanceof String str) {
System.out.println(str.length());
}Cải tiến API
Cải tiến CharSequence
Trước Java 15, nếu muốn kiểm tra một StringBuilder, StringBuffer hoặc CharBuffer có rỗng hay không, thông thường cần gọi length() == 0.
Interface CharSequence bổ sung default method isEmpty() để kiểm tra character sequence có rỗng hay không và trả về true nếu rỗng.
public interface CharSequence {
default boolean isEmpty() {
return this.length() == 0;
}
}Vì String, StringBuilder và các class khác đều implement interface này, giờ đây có thể viết logic kiểm tra theo cách thống nhất và giàu ngữ nghĩa hơn. Điều này đặc biệt phù hợp với việc viết code generic (xử lý nhiều loại character sequence).
Lưu ý: Class String vốn đã có method isEmpty(), nhưng đó là method do chính String định nghĩa; thay đổi trong Java 15 là đưa khả năng này lên interface.
Cải thiện performance của TreeMap
Đây là một tối ưu khá sâu. Mặc dù các method như putIfAbsent(), compute() đã xuất hiện trong interface Map từ Java 8, nhưng trước Java 15, TreeMap không tự implement các method này mà sử dụng trực tiếp default implementation trong interface.
Thay đổi trong Java 15: TreeMap override riêng các method sau:
putIfAbsent()computeIfAbsent()computeIfPresent()compute()merge()
Tại sao cần override?
- Cải thiện performance: default implementation trong interface thường khá “đơn giản”, thường cần tìm kiếm nhiều lần (chẳng hạn tìm xem có tồn tại trước không rồi mới quyết định insert).
- Đảm bảo O(log n): implementation được tối ưu của
TreeMapcó thể hợp nhất việc tìm kiếm và insert trong một lần duyệt red-black tree, tránh tìm kiếm cây lặp lại và cải thiện đáng kể hiệu suất thực thi khi xử lý dữ liệu quy mô lớn.
Các tính năng khác
- Nashorn JavaScript engine bị loại bỏ hoàn toàn: Nashorn là JavaScript engine được giới thiệu từ Java 8. Java 9 đã tăng cường Nashorn và triển khai một số tính năng mới của ES6. Trong Java 11, Nashorn đã bị deprecated; đến Java 15 thì bị xóa hoàn toàn.
- Tái cấu trúc DatagramSocket API
- Vô hiệu hóa và deprecated biased locking (Biased Locking): Việc đưa biased locking vào làm tăng độ phức tạp của JVM nhiều hơn mức cải thiện performance mà nó mang lại. Tuy nhiên, vẫn có thể dùng
-XX:+UseBiasedLockingđể bật biased locking, nhưng sẽ nhận được thông báo đây là API đã deprecated. - ……
Lời cuối
Nếu nội dung hữu ích với bạn, hãy tiện tay tặng JavaGuide một Star miễn phí để ủng hộ: GitHub | Gitee.
JavaGuide đã được duy trì gần bảy năm, tích lũy 6100+ commit, với sự chung tay hoàn thiện của 620+ contributor. Star, phản hồi và PR của bạn đều là động lực để dự án tiếp tục cập nhật.
Nếu bạn đang chuẩn bị phỏng vấn backend / phát triển ứng dụng AI, có thể tham khảo Knowledge Planet của tôi, bao gồm các project thực tế về backend và AI, tối ưu CV, hỏi đáp 1-1 và tài liệu về các trọng điểm thường gặp, đã được duy trì liên tục sáu năm.
