Java 11 Features
Java 11 (September 2018) was the first Long-Term Support (LTS) release after the move to a six-month cadence, succeeding Java 8 as the default production baseline for years. It’s an incremental but high-value release: quality-of-life additions to String, Files, and collections, a production-grade HttpClient, and ergonomic wins like running a .java file directly. Oracle also removed bundled modules (JavaFX, Java EE, CORBA) here, so it’s a real migration checkpoint, not just a feature drop.
LTS Context
| Version | Released | Type | Notable |
|---|---|---|---|
| 8 | 2014 | LTS | lambdas, streams, java.time |
| 11 | 2018 | LTS | HttpClient, var-in-lambda, String/Files APIs |
| 17 | 2021 | LTS | records, sealed classes, pattern matching |
| 21 | 2023 | LTS | virtual threads, pattern matching for switch |
LTS releases receive years of security and bug fixes. Pick an LTS as your production baseline and treat the interim feature releases as a preview channel.
var in Lambda Parameters
Java 10 added local-variable var; Java 11 extends it to lambda parameters. The sole practical benefit is the ability to attach annotations to an inferred parameter type.
// All three params must use var — you cannot mix var and explicit types.
BiFunction<Integer, Integer, Integer> add = (var a, var b) -> a + b;
list.stream()
.map((@NonNull var s) -> s.strip())
.forEach(System.out::println);
New String Methods
" ".isBlank(); // true — whitespace-only check
" hi ".strip(); // "hi" — Unicode-aware trim()
"ab".repeat(3); // "ababab"
"a\nb\nc".lines() // Stream<String> of lines
.count(); // 3
strip() improves on trim() by respecting the full Unicode whitespace definition. lines() returns a lazy Stream<String>, ideal for processing large text without splitting into an array.
Files.readString / writeString
Reading and writing an entire text file is now a single call, defaulting to UTF-8.
import java.nio.file.*;
Path p = Path.of("notes.txt");
Files.writeString(p, "first line\nsecond line");
String content = Files.readString(p);
System.out.println(content.lines().count());
Output:
2
The Standardized HttpClient
The java.net.http.HttpClient (incubated in 9/10, finalized in 11) replaces the clunky HttpURLConnection. It supports HTTP/2, WebSocket, and both synchronous and asynchronous calls.
import java.net.http.*;
import java.net.URI;
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://api.example.com/status"))
.header("Accept", "application/json")
.GET()
.build();
// Synchronous
HttpResponse<String> resp =
client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(resp.statusCode());
// Asynchronous
client.sendAsync(request, HttpResponse.BodyHandlers.ofString())
.thenApply(HttpResponse::body)
.thenAccept(System.out::println);
The client is immutable and reusable; create one and share it across requests.
Running Single-File Source Code
Java 11 lets you execute a source file directly, with no explicit javac step — perfect for scripts and quick experiments.
java Hello.java
The launcher compiles to memory and runs main in one shot. Combined with a shebang (#!/usr/bin/java --source 11), a .java file becomes an executable script.
Collection.toArray(IntFunction)
A cleaner overload for converting a collection to a typed array, replacing the zero-length-array idiom.
List<String> names = List.of("Ada", "Grace");
String[] arr = names.toArray(String[]::new); // Java 11
// old: names.toArray(new String[0]);
Feature Summary
| Feature | Why it matters |
|---|---|
var in lambdas | annotate inferred params |
isBlank/strip/repeat/lines | everyday String ergonomics |
Files.readString/writeString | one-line file I/O, UTF-8 default |
HttpClient | modern HTTP/2 + async, no dependencies |
java File.java | run sources without compiling |
toArray(IntFunction) | type-safe array conversion |
Best Practices
- Standardize on an LTS (11, 17, or 21) for production; reserve interim releases for evaluation.
- Reuse a single
HttpClientinstance; it manages a connection pool internally. - Prefer
strip()overtrim()in new code for correct Unicode handling. - Use
Files.readString/writeStringonly for files that comfortably fit in memory; stream larger files withFiles.linesorBufferedReader. - Limit
varto cases where the inferred type is obvious from the right-hand side — clarity beats brevity.