Java 11 (September 2018)¶
Release Information
Release Date: September 25, 2018 End of Support: September 2026 Theme: Modernization & Convenience
Overview¶
Java 11 is the first LTS release after Java 8 and represents a major milestone in Java's modernization. It introduced several convenience features that reduce boilerplate and improve developer productivity.
Local Variable Type Inference (var)¶
Introduced in Java 10, refined in Java 11
Java 10 introduced var for local variables. Java 11 extended it to lambda parameters.
The Problem¶
Explicit type declarations were verbose, especially with generics.
Before/After¶
// Verbose type declarations
Map<String, List<Customer>> customersByCity =
new HashMap<String, List<Customer>>();
BufferedReader reader =
new BufferedReader(new FileReader("data.txt"));
// In lambdas - no annotations possible
list.stream()
.map((String s) -> s.toUpperCase())
.collect(Collectors.toList());
When to Use var¶
Good Use Cases
Avoid When
HTTP Client API¶
Interview Favorite
Know that this replaced the old HttpURLConnection and supports HTTP/2.
The Problem¶
Java had no standard HTTP client. Developers relied on Apache HttpClient or OkHttp.
Before/After¶
// Old HttpURLConnection - verbose and painful
URL url = new URL("https://api.example.com/users");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
conn.setRequestProperty("Accept", "application/json");
int responseCode = conn.getResponseCode();
if (responseCode == 200) {
BufferedReader in = new BufferedReader(
new InputStreamReader(conn.getInputStream()));
String line;
StringBuilder response = new StringBuilder();
while ((line = in.readLine()) != null) {
response.append(line);
}
in.close();
}
// Modern HTTP Client - clean and powerful
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://api.example.com/users"))
.header("Accept", "application/json")
.GET()
.build();
// Synchronous
HttpResponse<String> response = client.send(
request,
HttpResponse.BodyHandlers.ofString()
);
System.out.println(response.body());
// Asynchronous
client.sendAsync(request, HttpResponse.BodyHandlers.ofString())
.thenApply(HttpResponse::body)
.thenAccept(System.out::println);
HTTP Client Features¶
| Feature | Description |
|---|---|
| HTTP/2 | Native support, automatic fallback to HTTP/1.1 |
| WebSocket | Built-in WebSocket client |
| Async | sendAsync() returns CompletableFuture |
| Body Handlers | ofString(), ofByteArray(), ofFile(), ofInputStream() |
POST Example¶
HttpRequest postRequest = HttpRequest.newBuilder()
.uri(URI.create("https://api.example.com/users"))
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(
"""
{"name": "John", "email": "john@example.com"}
"""
))
.build();
New String Methods¶
Overview¶
Java 11 added several convenience methods to the String class.
Methods¶
// strip() vs trim() - Unicode aware
String text = "\u2000 Hello World \u2000";
text.trim(); // "\u2000 Hello World \u2000" (doesn't remove Unicode whitespace)
text.strip(); // "Hello World" (removes all Unicode whitespace)
// Variants
text.stripLeading(); // "Hello World \u2000"
text.stripTrailing(); // "\u2000 Hello World"
Comparison Table¶
| Method | Purpose | Example |
|---|---|---|
isBlank() |
Check empty/whitespace | " ".isBlank() → true |
lines() |
Split by line breaks | "a\nb".lines() → Stream |
strip() |
Remove Unicode whitespace | " hi ".strip() → "hi" |
stripLeading() |
Remove leading whitespace | " hi ".stripLeading() → "hi " |
stripTrailing() |
Remove trailing whitespace | " hi ".stripTrailing() → " hi" |
repeat(n) |
Repeat n times | "ab".repeat(3) → "ababab" |
Files API Improvements¶
The Problem¶
Reading/writing entire files required multiple lines of boilerplate.
Before/After¶
// Reading a file
String content = new String(
Files.readAllBytes(Paths.get("file.txt")),
StandardCharsets.UTF_8
);
// Writing a file
Files.write(
Paths.get("file.txt"),
content.getBytes(StandardCharsets.UTF_8)
);
// Reading lines
List<String> lines = Files.readAllLines(
Paths.get("file.txt"),
StandardCharsets.UTF_8
);
Collection Factory Methods¶
Introduced in Java 9
While technically Java 9, these are essential knowledge for Java 11 developers.
Before/After¶
// Creating immutable list
List<String> list = Collections.unmodifiableList(
Arrays.asList("a", "b", "c")
);
// Creating immutable set
Set<String> set = Collections.unmodifiableSet(
new HashSet<>(Arrays.asList("a", "b", "c"))
);
// Creating immutable map
Map<String, Integer> map = new HashMap<>();
map.put("a", 1);
map.put("b", 2);
map = Collections.unmodifiableMap(map);
// Immutable collections in one line
List<String> list = List.of("a", "b", "c");
Set<String> set = Set.of("a", "b", "c");
Map<String, Integer> map = Map.of(
"a", 1,
"b", 2,
"c", 3
);
// For more than 10 entries
Map<String, Integer> largeMap = Map.ofEntries(
Map.entry("a", 1),
Map.entry("b", 2),
// ... more entries
);
Optional Improvements¶
New Methods in Java 11¶
Optional<String> opt = Optional.of("value");
// isEmpty() - opposite of isPresent()
if (opt.isEmpty()) {
// handle empty case
}
// or() - provide alternative Optional
Optional<String> result = findInCache()
.or(() -> findInDatabase())
.or(() -> Optional.of("default"));
// ifPresentOrElse() - handle both cases
opt.ifPresentOrElse(
value -> System.out.println("Found: " + value),
() -> System.out.println("Not found")
);
// stream() - convert to stream (0 or 1 element)
List<String> values = optionals.stream()
.flatMap(Optional::stream)
.collect(Collectors.toList());
Running Single-File Programs¶
Before/After¶
Quick Reference¶
// var
var list = new ArrayList<String>();
var map = Map.of("key", "value");
// HTTP Client
HttpClient.newHttpClient()
.send(request, HttpResponse.BodyHandlers.ofString());
// String methods
" text ".strip(); // "text"
"text".isBlank(); // false
"line1\nline2".lines(); // Stream<String>
"-".repeat(10); // "----------"
// Files
String content = Files.readString(Path.of("file.txt"));
Files.writeString(Path.of("file.txt"), content);
// Collections
List.of("a", "b", "c");
Set.of(1, 2, 3);
Map.of("key", "value");