Stay on top of Java news from 17 to 21
Hey there! Are you curious to know what exciting new features Java has introduced in the latest version, 21? Well, you've come to the right place! Keep reading to discover some cool things that Java has introduced to help you become more productive.
If you are not updated with the improvements from Java 17, I recommend reading this article first: Keep updated with the news from Java 11 to Java 17.
Java 18
Java 18 introduced some new things and also contains some upgrades in preview features, like JEP 420: Pattern Matching for switch (Second Preview). Let’s see some of the new features:
UTF-8 by Default (JEP 400)
Starting with JDK 18, UTF-8 is the default charset for the Java SE APIs. APIs that depend on the default charset behave consistently across all JDK implementations and independently of the user’s operating system, locale, and configuration. Specifically, java.nio.charset.Charset#defaultCharset() now returns UTF-8 charset by default. The file.encoding system property is now a part of the implementation specification, which may accept UTF-8 or COMPAT. The latter is a new property value that instructs the runtime to behave as previous releases. This change is significant to users who call APIs that depend on the default charset. Users can determine whether they'd be affected or not, by specifying -Dfile.encoding=UTF-8 as the command line option with the existing Java runtime environment.
Deprecate Finalization for Removal (JEP 421)
The finalization mechanism has been deprecated for removal in a future release. The finalize methods in standard Java APIs, such as Object.finalize() and Enum.finalize(), have also been deprecated for removal in a future release, along with methods related to finalization, such as Runtime.runFinalization() and System.runFinalization().
Finalization remains enabled by default, but it can be disabled for testing purposes by using the command-line option --finalization=disabled introduced in this release. Maintainers of libraries and applications that rely upon finalization should migrate to other resource management techniques in their code, such as try-with-resources and cleaners.
Code Snippets in Java API Documentation (JEP 413)
An @snippet tag for JavaDoc's Standard Doclet has been added, to simplify the inclusion of example source code in API documentation.
For further details, see Programmer's Guide to Snippets.
If you want to know more about what's new in Java 18:
https://www.oracle.com/java/technologies/javase/18all-relnotes.html
https://openjdk.org/projects/jdk/18/
Java 19
This version also introduced more features, and some preview features, which we will see now.
Record Patterns (JEP 405 Preview)
With this JEP, it is possible to use pattern matching with Record. Record patterns and type patterns can be nested to enable a powerful, declarative, and composable form of data navigation and processing.
record Point(int x, int y) {}
static void printSum(Object o) {
if (o instanceof Point p) {
int x = p.x(); int y = p.y();
System.out.println(x+y);
}
}
Pattern Matching for switch (JEP 427 Third Preview)
With this JEP, the switch allows null. Traditionally, switch statements and expressions throw NullPointerException if the selector expression evaluates to null. However, now, with a case null, the switch executes the code associated with that label; without a case null, the switch throws NullPointerException.
switch (s) {
case null -> System.out.println("Oops");
case "Foo", "Bar" -> System.out.println("Great");
default -> System.out.println("Ok");
}
With this JEP it's also possible to create conditionals in the switch expression, called dominance of pattern labels.
Integer i = ...
switch (i) {
case -1, 1 -> ... // Special cases
case Integer i when i > 0 -> ... // Positive integer cases
case Integer i -> ... // All the remaining integers
}
Virtual Threads (JEP 425 Preview)
Virtual threads are lightweight threads that dramatically reduce the effort of writing, maintaining, and observing high-throughput concurrent applications.
try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
IntStream.range(0, 10_000).forEach(i -> {
executor.submit(() -> {
Thread.sleep(Duration.ofSeconds(1));
return i;
});
});
} // executor.close() is called implicitly, and waits
If you want to understand more about the benefits of Virtual Threads, you can see this benchmark: Micro Benchmark using Project Loom.
If you want to know more about what's new in Java 19:
Java 20
In this version, we have several upgrades to previous features, so let’s see some of these improvements
Pattern Matching for switch (JEP 427 Fourth Preview)
The main changes in this JEP since the third preview are:
An exhaustive switch (i.e., a
switch
expression or a patternswitch
statement) over anenum
class now throwsMatchException
rather thanIncompatibleClassChangeError
if no switch label applies at run time.The grammar for switch labels is simpler.
Inference of type arguments for generic record patterns is now supported in
switch
expressions and statements, along with the other constructs that support patterns.
With that, we can have a compilation error if our switch doesn’t match for all the cases. This is very useful for Enum, and also for sealed classes.
sealed interface S permits A, B, C {}
final class A implements S {}
final class B implements S {}
record C(int i) implements S {} // Implicitly final
static int testSealedExhaustive(S s) {
return switch (s) { // Error - not exhaustive, missing B or default
case A a -> 1;
case C c -> 3;
};
}
With enum is the same:
enum Color { RED, GREEN, BLUE; }
static void typeTester(Color color) {
switch (color) { // Error - not exhaustive, missing BLUE or default
case null -> System.out.println("null");
case RED red -> System.out.println("Color: " + c.toString());
case GREEN green -> System.out.println("Record class: " + p.toString());
}
}
JEP 432: Record Patterns (Second Preview)
This JEP provides the usage of pattern matching for Records. This is the second preview, which means that this JEP has some improvements since the first preview.
public record Pokemon(String name, String type){};
public String getPokemonName(Object object) {
if(object instanceof Pokemon(String name, String type)){
return name;
}
return "";
}
If you want to know more about what's new in Java 20:
Java 21
This is the latest version we are going to discuss here, and this is an LTS version, or at least, there are vendors that keep this version for Long-Term Support 😊
In this version, many features that we saw in the preview are ready to be used in production, as JEP 440: Record Patterns, JEP 441: Pattern Matching for switch and JEP 444: Virtual Threads.
Not only that, but we also have new features, let’s go deep into that.
JEP 430: String Templates (Preview)
String templates complement Java's existing string literals and text blocks by coupling literal text with embedded expressions and template processors to produce specialized results.
public String writePokemonStringTemplate(PokemonRecord pokemon) {
return STR. """
{
"id": \{ pokemon.id() },
"name": "\{ pokemon.name() }",
"type": [
"\{ String.join("\",\"", pokemon.type()) }"
],
"species": "\{ pokemon.species() }",
}
""" ;
}
public record PokemonRecord(Integer id, String name, List<String> type, String species) {}
PS: in the IDE the visualization is much better 😅
JEP 431: Sequenced Collections
This JEP introduces new interfaces for ordered collections, with uniform APIs for accessing the first and last elements and processing elements in reverse.
public String getFirst(SequencedCollection<String> collection){
return collection.getFirst();
}
public String getLast(SequencedCollection<String> collection){
return collection.getLast();
}
public SequencedCollection<String> reverse(SequencedCollection<String> collection){
return collection.reversed();
}
public Map.Entry<String, String> getFirst(SequencedMap<String, String> collection){
return collection.firstEntry();
}
public Map.Entry<String, String> getLast(SequencedMap<String, String> collection){
return collection.lastEntry();
}
public SequencedMap<String, String> reverse(SequencedMap<String, String> collection){
return collection.reversed();
}
JEP 443: Unnamed Patterns and Variables (Preview)
This JEP improves the readability of record patterns by eliding unnecessary nested patterns.
Using the underscore (_) to correspond to the variable that you don’t need, makes the code cleaner, and easy to read.
public String getPokemonDetailsFromPokeball(Object obj) {
if (obj instanceof Pokeball(String name, PokemonRecord(_, String pokemonName, _, _))) {
return "Pokeball: " + name + " - Pokemon: " + pokemonName;
}
return null;
}
record Pokeball(String name, PokemonRecord pokemonRecord) {
}
record PokemonRecord(Integer id, String pokemonName, List<String> type, String species) {
}
If you want to know more about what's new in Java 21:
If you want to see some samples with this code, take a look here, https://github.com/ThiagoBfim/java-news.
Conclusion
Java has improved a lot, now we have better ways of doing old things. We have records, sealed classes, pattern matching, virtual threads, and more that can help with developer productivity.
This article is just an introduction to what's new in Java to help you in your daily activities, but be aware that there are many other things and improvements to the JVM and the Garbage Collector.
So keep pushing yourself to learn more about Java and stay up to date with the latest news. Your dedication and hard work will pay off in the end! 😄