Java used to have a new version every 3 to 4 years until Java 9 release. After Java 9 we have a 6 months cadence for releasing a new Java version. Since September 2017 until now, we have had 6 different Java versions, with an LTS version (Java 11). At this moment, the latest Java 14 is the latest version. So, it’s not easy to keep in mind all the new features that are being added to Java with every release. The goal of this article is to provide a summary of the main features that a Java Developer should keep in mind from Java 9 to Java 14.
In order to organize better all this information, this post will be split into 3 parts:
– Part 1 (Java 9 to Java 11)
– Part 2 (Java 12 to Java 14)
– Part 3 (A comparison between Java 8 code to Java 14).
Note: It’s important to know that some of those features are preview-features, which means they are not enabled by default, and its implementation can change in future java versions. In order to enable the preview features you need to set the flag --enable-preview
in the command line, IDE or shell. For example:
JSHELL$jshell --enable-preview
Command line$java --enable-preview --source {java-version} MyTestClass.java
Java 12
Some of its features are preview enabled. I will detail more in next java versions where these features have enhancements or are not preview anymore.
Some other code features are:
– File Mismatch method
This method is helpful to know if 2 files are the same or not. If the files are identical it returns a -1. In the other hand, if they are different the method returns the size of the smaller file or the first position where the have a difference.
– Java String new methods
4 new methods have been added to the String
class. They will be helpful for a future feature Text Blocks
, for now you probable won’t use them.
indent(int n)
transform(Function f)
Optional describeConstable()
String resolveConstantDesc(MethodHandles.Lookup lookup)
– Compact Number Formating
It’s not a big feature, but it will be helpful if you want to display big numbers in a compact format, for example: A value like 10120 displayed as 10.1k, or 212000 as 212k.
NumberFormat formatter = NumberFormat .getCompactNumberInstance(new Locale("en", "US"),NumberFormat.Style.SHORT); formatter.setMaximumFractionDigits(1); System.out.println(formatter.format(10120)); //Prints 10.1k
Java 13
The same as previous version, it has some preview features that we should enable in other to use them.
- Switch expressions (still preview mode)
- Text Blocks
From the new code features side, the more importants are:
– New Implementation for Socket API
There is no change in how we create Sockets using the interfaces java.net.Socket
and java.net.ServerSocket
. It’s the underlying implementation of the java.net.Socket
and java.net.ServerSocket
APIs which have been rewritten. The new implementation, NioSocketImpl
, is a drop-in replacement for the previous PlainSocketImpl
. It uses java.util.concurrent
locks rather than synchronized methods.
– More new methods in String class
There are three new methods in the String class, associated with the text blocks feature.
formatted(Object… args):
it’s similar to the String format() method. It’s added to support formatting with the text blocks.stripIndent():
used to remove the incidental white space characters from the beginning and end of every line in the text block. This method is used by the text blocks and it preserves the relative indentation of the content.translateEscapes():
returns a string whose value is this string, with escape sequences translated as if in a string literal.
Java 14
This version has more improvements in some of the previous mentioned preview features, Switch Expressions (no more preview), a very helpful improvent in the NullPointerException message and some other JVM and GC enhancements.
– Switch Expressions
Java 14 has finally bring switch as expression and not as an statement, and this is part of the standard language (not a preview feature). We can continue using the switch as an statement like in previous Java versions, but the switch with the ->
operator and the yield
instruction will allow us to use it as an expression.
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);
Some importants things to keep in mind.
- We use the
->
operator for switch expressions, instead of the:
operator used in switch statment. - It is required to have a default section
yield
is used to return a value for the case.- It’s not required the
break
statement into each case to stop the flow.
– Pattern Matching for Instance Of
Very simple but helpful change!!! We won’t need to cast the object after one instanceof statement in order to use it safely.
//Previous Java 14 if (obj instanceof User) { User user = (User) obj; System.out.println(user.getName()); } //Java 14 and beyond if (obj instanceof User user) { System.out.println(user.getName()); }
– Text Blocks
Text Blocks were introduced in Java 13 as preview feature, and it continues as a preview feature in Java 14 with some enhancements. It allows us to create multiline strings easily. The multiline string has to be written inside a pair of triple-double quotes.
String sqlSentence = """ select * from Item i where i.price > 5000 and i.saleDate = '01/01/2020' """; String textBlockJSON = """ { "name":"Pankaj", "website":"JournalDev" }""";
If we mix the Text Block with the some of the method added in the String class like: formatted, stripIndent, and more, it will be a good way to create templates.
String textBlockHTML = """ <html> <head> <title>%s</title> </head> <body> <h1>%s</h1> </body> </html> """.formatted("My title", "Hello World");
– Records
This is one of my favorite new features added in Java (still in preview mode). It reduces a lot of our code, and I am sure I will be a good option for the famous DTO (Data Transfer Object).
A record compacts the sintax for declaring a class that stores pure inmutable data, and has no logic. It’s similar to the Data Class in Kotlin or the Case Class in Scala. Records avoid to add boiler plate code because the constructor, accessors (getters-setters), equals
, hashCode
and toString
methods are generated automatically.
public record Person (String name, String lastName, int age){}
If we want to do the same with a regular Java Class, we might need to generate something like the following code.
public class Person { private String name; private String lastName; private int age; public String getName(){ return name; } public void setName(String name){ this.name = name; } public String getLastName(){/*Code*/} public void setLastName(String lastName){/*Code*/} public int getAge(){/*Code*/} public void setAge(int age){/*Code*/} public boolean equals(Object obj){/*Code*/} public int hashCode(){/*Code*/} public String toString(){/*Code*/} }
For sure, the classic POJOs (Plain Old Java Object) are still valid, but now we have another structure to use in our code according to our requirements. That’s why it is import to keep in mind the following characteristics of a record.
- The declared fields are private and final.
- Accesors or autogenerated methods can be redifined.
- It is possible to create new methods into a record.
- Records don’t allow to create instance fields in its body.
- Records allow to create static fields in its body.
- Records allow multiple constructors.
- Records can implement Interfaces
- Records can not extend other classes.
- Records can not be abstract.
– Helpful NullPointerException message
Previous to Java 14 when we face a NullPointerException, we get a message that indicates the line when the NPE happened, but we don’t know which value was null. Now, in those cases, we will see a more detailed message that indicates the variable, call or object that we try to access and it was null.
//Before Exception in thread "main" java.lang.NullPointerException at NullPointerExample.main(NullPointerExample.java:5) //New message Exception in thread "main" java.lang.NullPointerException: Cannot invoke "User.getName()" because the return value of "Articule.getUser()" is null at NullPointerExample.main(NullPointerExample.java:5)
As we can see, we will now the exact call that is return a null and the incorrect use of it.
References
- https://www.journaldev.com/28666/java-12-features
- https://www.journaldev.com/33204/java-13-features
- https://www.journaldev.com/37273/java-14-features
- https://www.logicbig.com/tutorials/core-java-tutorial/java-14-changes/records.html
[…] this information, this post will be split into 3 parts: – Part 1 (Java 9 to Java 11)– Part 2 (Java 12 to Java 14)– Part 3 (A comparison between Java 8 code to Java […]
[…] all this information, this post will be split into 3 parts: – Part 1 (Java 9 to Java 11)– Part 2 (Java 12 to Java 14)– Part 3 (A comparison between Java 8 code to Java […]