Martin Ahrer

Thinking outside the box

Java 11 major language and API improvements

2024-07-24 3 min read Martin

Java LTS Release Adoption

Before we go into details of the enhancements and additions of Java ⑪ lets briefly look at new relic’s yearly State of the Java Ecosystem 2024 report.

new relic 2024 State of the Java Ecosystem

Even though Java ⑪ LTS was released in 2018, in 2020 only ~11% of the projects have been using it. Java ⑧ was still the dominant Java release. In 2023 usage was still at 33% and only dropped to around 28% in 2024.

Java ⑩ was the last free Oracle JDK release that could be used commercially without a license. Starting with Java ⑪, there’s no free long-term support (LTS) from Oracle.

The following content is summarizing the most important changes to the Java API and the Java language introduced with Java ⑪.

For a more complete overview follow the links in the following sections referring to the official Oracle release documents.

Language improvements

The following describes selected improvements of the Java language. See the Java 10 release notes.

Lambda Local Variable

Lambda variable without type with Java ⑩
Function<Integer, Integer> doubled = (a) -> a * 2;
Lambda variable with type with Java ⑩
Function<Integer, Integer> doubled = (Integer a) -> a * 2;

The type is inferred from the initializer.

With multiple lambda variables we have to use var for all or none. Also it is not possible to mix var with explicit types.

Lambda variable with Java ⑪
Function<Integer, Integer> doubled = (var a) -> a * 2;
Annotated lambda variable with Java ⑪
Function<Integer, Integer> doubled = (@NonNull var a) -> a * 2; (1)
1With var the lambda variable can be annotated without having to specify the type.

API improvements

The following describes selected improvements of the Java API. See the Java 11 release notes.

Predicate

Before Java 11 we had to use Predicate::negate and it was not possible to use a method reference. With Predicate::not we can use method references and Predicate::not reads more natural.

Not
var string = "Java 11 rocks!";

Assertions.assertEquals(string,
        Stream.of(string)
                .filter(Predicate.not(String::isBlank))
                .toList().get(0));

String

Lines
var multiline = """
    Java
    11
    rocks!
    """;
Assertions.assertIterableEquals(
    Arrays.asList("Java", "11", "rocks!"),
    multiline.lines().toList());

With String::lines we can split any multi line String into a stream of lines.

Strip
var strings = Arrays.asList("Java", " 11 ", "rocks!");
Assertions.assertIterableEquals(
    Arrays.asList("Java", "11", "rocks!"),
    strings.stream().map(String::strip).toList());

String::strip is similar to String::trim but with Unicode support. String also has a stripLeading and stripTrailing method.

Repeat
Assertions.assertEquals("***", "*".repeat(3));

With String::repeat we can build a string from repeating a string.

Files

Files.readString() and Files.writeString()
Path filePath = Files.writeString(Files.createTempFile(tmpdir, "version", ".properties"), "11");
String version = Files.readString(filePath);
assertEquals("11", version);

Collection

To Array
var list = Arrays.asList("Java", "11", "rocks");
String[] array = list.toArray(String[]::new);