Java 11 major language and API improvements
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.

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
Function<Integer, Integer> doubled = (a) -> a * 2;
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.
Function<Integer, Integer> doubled = (var a) -> a * 2;
Function<Integer, Integer> doubled = (@NonNull var a) -> a * 2; (1)
1 | With 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.
var string = "Java 11 rocks!";
Assertions.assertEquals(string,
Stream.of(string)
.filter(Predicate.not(String::isBlank))
.toList().get(0));
String
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.
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.
Assertions.assertEquals("***", "*".repeat(3));
With String::repeat
we can build a string from repeating a string.
Files
Path filePath = Files.writeString(Files.createTempFile(tmpdir, "version", ".properties"), "11");
String version = Files.readString(filePath);
assertEquals("11", version);
Collection
var list = Arrays.asList("Java", "11", "rocks");
String[] array = list.toArray(String[]::new);