1. New Language Features in Java 14
2. Updates for Tools and APIs in Java 14
3. JVM Performance Improvements in JDK 14
4. What’s Deprecated in JDK 14
Now, let’s dive into the details for what’s new, deprecated in removed in Java 14.public void dayOfMonth(int month) { switch (month) { case 1: case 3: case 5: case 7: case 8: case 10: case 12: System.out.println("this month has 31 days"); break; case 2: System.out.println("this month has 28 or 29 days"); break; case 4: case 6: case 9: case 11: System.out.println("this month has 30 days"); break; default: System.out.println("invalid month number"); } }This is clearly very verbose. Now with Java 14’s enhancements for switch expression, we can rewrite this method as follows:
public static void dayOfMonth(int month) { switch (month) { case 1, 3, 5, 7, 8, 10, 12 -> System.out.println("this month has 31 days"); case 4, 6, 9, 11 -> System.out.println("this month has 30 days"); case 2 -> System.out.println("this month probably has 28 days"); default -> System.out.println("invalid month number"); } }You see, it’s much clearer and more readable, isn’t it?
int days = switch(month) { case 1, 3, 5, 7, 8, 10, 12 -> 31; case 4, 6, 9, 11 -> 30; case 2 -> 28; default -> 0; };If the code in a case is a block, we can use the yield keyword to return the value, for example:
int days = switch(month) { case 1, 3, 5, 7, 8, 10, 12 -> 31; case 4, 6, 9, 11 -> 30; case 2 -> { System.out.print("Enter year: "); Scanner scanner = new Scanner(System.in); int year = scanner.nextInt(); if (year % 4 == 0) yield 29; else yield 28; } default -> 0; };So, since Java 14, yield becomes the keyword used in switch expression to return a value. Read the JDK Enhancement Proposal JEP 361 that covers the full detailed of enhancements for switch expression.For more code examples with detailed explanation, read this post Java 14: Switch Expressions Enhancements Examples.
String html = "<html>\n" + " <head>\n" + " <title>Homepage</title>\n" + " </head>\n" + " <body>\n" + " <h1>This is the homepage</h1>\n" + " </body>\n" + "</html>\n";From Java 14, you can rewrite this String literal as follows:
String html = """ <html> <head> <title>Homepage</title> </head> <body> <h1>This is the homepage</h1> </body> </html> """;You see, it looks much more naturally, right? A text bock starts with 3 double quotes follow by a new line character, and ends with 3 double quotes.With text block, you don’t have to escape special characters like new lines or double quotes. Note that the Java compiler will automatically trim the leading spaces in a text block, making it more convenient for programmers.Read the JEP 368 that describes text block in full details.Update: Text blocks become a standard feature in JDK 15. Learn more: Understand Text Blocks Feature in Java 15?
public class Book { private String title; private String author; public Book(String title, String author) { this.title = title; this.author = author; } public void setTitle(String title) { this.title = title; } public String getTitle() { return this.title; } public void setAuthor(String author) { this.author = author; } public String getAuthor() { return this.author; } }Now, with the new record type, you can simply write:
record Book (String title, String author) { }Then the Java compiler will automatically generate appropriate fields, constructor, getter and setter methods. In addition, a record also implements equals(), hashCode() and toString() methods implicitly.Read the JEP 359 for more information about Records features.
if (obj instanceof String) { String s = (String) obj; // use s }Here, the statement that casts the obj object to a type of String is somewhat verbose because when the if statement evaluates to true, the type of the object is indeed String. Now with Java 14, we can improve the instanceof statement as follows:
if (obj instanceof String s) { // we use s directly here }As you can see, it eliminates the verbose cast statement. More advanced, we can add expression to the right like this:
if (obj instanceof String s && s.length() > 5) { // use String s if its length > 5 }This would make the use of instanceof operator more flexible and concise. Read the JEP 305 that covers the greater details of pattern matching for instanceof.Note that the preview features require the switches --enable-preview and --source 14 when compiling and running. Preview features need further feedback and improvements until they become finalized in future releases of JDK.
jpackage --name CodeJavaForm --input dist --main-jar GUIFormExamples.jar --main-class examples.ContactEditor --type msi --win-dir-chooser --win-menu --win-shortcutAnd I got a nice installer program that looks like this:So I think for the first time in history, programmers can create native installer programs for their Java applications with ease. Read the JEP 343 for more information about packaging tool in JDK 14.
class A { int i; } class B { int j; }And a statement that uses object references of A and B like this:
a.i = b.j;If NullPointerException throws at this line, JVM will terminate with the following error message:
Exception in thread "main" java.lang.NullPointerException at MyProgram.test(MyProgram.java:14) at MyProgram.main(MyProgram.java:6)It points exactly the line where the exception occurred. But wait, which variable is null in this case, a or b??? So programmers have to debug the program or write some checking code to know which a or b is null.The good news is, JDK 14 now computes the null-detail message to help programmers quickly and exactly identify which variable is null. To enable null-detail message, we must specify the following switch when running Java program:
java -XX:+ShowCodeDetailsInExceptionMessages MyProgramThen JVM will produce more meaningful error message like this:
Exception in thread "main" java.lang.NullPointerException: Cannot assign field "i" because "this.a" is null at MyProgram.test(MyProgram.java:14) at MyProgram.main(MyProgram.java:6)I think this is a cool feature that saves programmer’s time in debugging their code. Read the JEP 358 for more details.