Home Post Core Java

Modern Java - What’s new in Java 9 to Java 17

Mar 31, 2024

In a recent development new version of Java is now released in every six months, that means we get two Java versions every year.

Another thing Java is doing is to release LTS (Long Term Support) versions every three year.

Java Versioning
Version Release Date Remark
Java 1.0 January 1996 The first stable version, JDK 1.0.2, is called Java 1.
J2SE 5.0 September 2004 Generics, Autoboxing, Enums, Enhanced for Loops
Java SE 8 (LTS) March 2014 Lambda, Functional-style operations, Static Methods in Interfaces, Streams.
Java SE 9 September 2017 Modularization of the JDK
Java SE 10 March 2018 Time based release versioning started. Local Variable Type Inference
Java SE 11 (LTS) September 2018
Java SE 12 March 2019
Java SE 13 September 2019
Java SE 14 March 2020 Switch Expressions
Java SE 15 September 2020 Text Blocks
Java SE 16 March 2021 Record Classes
Java SE 17 (LTS) September 2021

1) Java 9

1.1) Collection Initialization

List.Of()

It returns an unmodifiable List containing the elements of the given Collection, in its iteration order.

Set.Of()

Returns an unmodifiable Set containing the elements of the given Collection.

Map.Of()

Returns an unmodifiable Map containing the entries of the given Map.

2) Java 10

2.1) List, Set and Map - copyOf() method

List.copyOf()

Returns an unmodifiable List containing the elements of the given Collection, in its iteration order.

The given Collection must not be null, and it must not contain any null elements.

If the given Collection is subsequently modified, the returned List will not reflect such modifications.

Set.copyOf()

Returns an unmodifiable Set containing the elements of the given Collection.

The given Collection must not be null, and it must not contain any null elements.

If the given Collection contains duplicate elements, an arbitrary element of the duplicates is preserved.

If the given Collection is subsequently modified, the returned Set will not reflect such modifications.

Map.copyOf()

Returns an unmodifiable Map containing the entries of the given Map.

The given Map must not be null, and it must not contain any null keys or values.

If the given Map is subsequently modified, the returned Map will not reflect such modifications.

2.2) Type Inference

Java 10 introduced local variable type inference.

The "var" is not a keywork.

It can not be used for variable declarations without an explicit initialisation, it can not be assigned to null either.

Also, "var" cannot be used with fields and in method signatures. It's only for local variables.

It can not be used with lambda expressions because they require an explicit target-type.

3) Java 11

3.1) Files.readString() and Files.writeString()

Files.readString()

It reads all content from a file into a string, decoding from bytes to characters using the UTF-8 charset.

The method ensures that the file is closed when all content have been read or an I/O error, or other runtime exception, is thrown.

/resources/exampleFile.txt
This is line 1
This is line 2
This is line 3
This is line 4

Files.writeString()

It write a CharSequence to a file.

Output: /resources/exampleFile.txt
{
   "name":"John",
   "age":30,
   "car":null
}

3.2) Predicate.not()

It returns a predicate that is the negation of the supplied predicate.

3.3) String - isBlank()

It returns true if the string is empty or contains only white space codepoints, otherwise false.

It does not check for a null and if called on a null String, a NullPointerException will be thrown.

3.4) String - strip()

It returns a string with all leading and trailing white space removed.

If all code points in input string are white space, then an empty string is returned.

3.5) String - lines()

It returns a stream of lines extracted from this string, separated by line terminators.

4) Java 12

4.1) Switch Expressions

Java SE 12 introduced switch expressions, which (like all expressions) evaluate to a single value, and can be used in statements.

It also introduced "arrow case" labels that eliminate the need for break statements to prevent fall through.

5) Java 13

4.1) Switch Expressions

Java SE 13 introduces one change to switch expressions: To specify their value, use the new yield statement instead of the break statement.

The yield statement makes it easier for us to differentiate between switch statements and switch expressions.

A switch statement can be the target of a break statement; conversely, a switch expression can be the target of a yield statement.

6) Java 14

6.1) Helpful NullPointerException

Java 14 (JEP 358) improves the usability of NullPointerException generated by the JVM by describing precisely which variable was null.

Before Java 13
Exception in thread "main" java.lang.NullPointerException
	at com.tb.java14.UsefulNullPointerException.main(UsefulNullPointerException.java:6)

After Java 13
Exception in thread "main" java.lang.NullPointerException: Cannot invoke "String.trim()" because "str" is null
	at com.tb.java14.UsefulNullPointerException.main(UsefulNullPointerException.java:6)

6.2) New instanceof()

Java 14 brings an improved version of the instanceof operator that both tests the parameter and assigns it to a binding variable of the proper type.

7) Java 15

7.1) Text Blocks

Text blocks are available in Java 13 and 14 as a preview feature and from Java 15 as a standard feature.

8) Java 16

8.1) Records

Records are available in Java 14 and 15 as a preview feature and from Java 16 as a standard feature.

From JDK 16, data classes (Entity Classes, POJO) can be replaced with records.

Records are immutable data classes that require only the type and name of fields.

The equals, hashCode, and toString methods, as well as the private, final fields, and public constructor, are generated by the Java compiler.

Records are similar to enums in the fact that they are a restricted form of class.

Defining a record is a concise way of defining an immutable data holding object.

9) Java 17

9.1) Sealed Classes

Sealed classes and interfaces restrict which other classes or interfaces may extend or implement them.

The "sealed" modifier seal a class and it can only be extended by classes passed in "permits" clause.

A sealed class must have at least one subclass and any sub-class extending a sealed class can be either "sealed", "non-sealed" or "final".

Sub-class declared in "permits" clause, must be in the "same module" or in the "same package".

Sealed classes "can also be declared without permit clause", in that case they can be extended by any class, but other rules remain same.

Sealed Interfaces are declared exactly the same way as the Sealed classes.

Source Code

avatar

NK Chauhan

NK Chauhan is a Principal Software Engineer with one of the biggest E Commerce company in the World.

Chauhan has around 12 Yrs of experience with a focus on JVM based technologies and Big Data.

His hobbies include playing Cricket, Video Games and hanging with friends.

Categories
Spring Framework
Microservices
BigData
Core Java
Java Concurrency