var for local variables and lambda parameters, new String methods (isBlank, lines, strip, repeat), Files.readString, the standard java.net.http.HttpClient, and running a source file directly with java File.java. Every example below was compiled and run on a real JDK 11; the ones that break were run on JDK 8 and 11 side by side so you can see the real error.
| Area | Java 8 | Java 11 |
|---|---|---|
| Local variables | Always write the type | var list = new ArrayList<String>(); (var arrived in Java 10, JEP 286) |
| Blank-string check | s.trim().isEmpty() | s.isBlank() |
| Read a file into a String | Several lines with Files.readAllBytes and a charset | Files.readString(path) |
| HTTP client | HttpURLConnection or a library | java.net.http.HttpClient (JEP 321) |
| Run a one-file program | javac then java | java Hello.java (JEP 330) |
| JAXB, JAX-WS, CORBA | Inside the JDK | Removed (JEP 320); add them as dependencies |
Tested against. Temurin 11.0.32.1 for every Java 11 demo, and Temurin 1.8.0_504 where a comparison with Java 8 is shown. The JEP list comes from the JDK 11 project page (general availability 25 September 2018). The runnable project is the java11-features module; ./run.sh regenerates every output quoted here.
What Java 11 added, what it removed, in one picture
Java 8 to Java 11 is not one release, it is three: 9, 10 and 11 all happened in between. Java 9 brought the module system (JEP 261), JShell (JEP 222) and theList.of/Set.of/Map.of factory methods (JEP 269); Java 10 brought var (JEP 286); Java 11 completed the set and cleaned house. The picture below groups what matters for a Java 8 developer.
New String methods: isBlank, strip, lines, repeat
Java 11 added five handyString methods. The surprise is strip() versus the old trim(): trim() removes only characters up to U+0020 (space and control characters), while strip() removes anything Unicode considers whitespace. The demo pads a word with an EM SPACE (U+2003) to show the difference. Source: StringMethods.java.
String em = String.valueOf((char) 0x2003); // EM SPACE
String padded = em + " hello " + em;
System.out.println("trim() length : " + padded.trim().length());
System.out.println("strip() length : " + padded.strip().length());
Output on JDK 11, from 01-string-methods.txt:
trim() length : 9
strip() length : 5
isBlank(" ") : true isEmpty: false
lines() : [a, b, c]
repeat(3) : ababab
stripLeading : [x ] stripTrailing: [ x]
trim() left all nine characters in place because the EM SPACE is above U+0020; strip() removed it and returned the five letters. isBlank() is true for a string of only whitespace, where isEmpty() is false. lines() splits on \n, \r and \r\n (the demo input contains both styles and still gives three lines) and returns a stream.
The same file on Java 8 does not compile. These methods do not exist before 11, and the compiler says so for each one (08-string-methods-on-8.txt):src/StringMethods.java:9: error: cannot find symbolsymbol: method strip()
Files.readString and Path.of
Reading a small text file used to take a stream or areadAllBytes plus a charset. Java 11 adds Files.readString and Files.writeString (UTF-8 by default), and Path.of as a shorter way to build a path. Source: FilesDemo.java.
Files.writeString(p, "one\ntwo\nthree");
String s = Files.readString(p);
Path.of("a", "b", "c.txt");
read back : one|two|three
Path.of : a/b/c.txt
That is 02-files.txt. readString loads the whole file into memory, so it suits config files and fixtures, not multi-gigabyte logs; for those see the NIO.2 guide to streaming large files.
The standard HttpClient (JEP 321)
java.net.http.HttpClient was incubated in Java 9 and 10 and became standard in 11. It supports HTTP/1.1 and HTTP/2, synchronous and asynchronous calls, and a builder-style request. The demo starts a tiny local server (com.sun.net.httpserver) so that the output is stable and needs no internet. Source: HttpClientDemo.java.
HttpClient client = HttpClient.newHttpClient();
HttpRequest req = HttpRequest.newBuilder(URI.create(url)).GET().build();
HttpResponse<String> r = client.send(req, HttpResponse.BodyHandlers.ofString());
CompletableFuture<String> f = client.sendAsync(req, HttpResponse.BodyHandlers.ofString())
.thenApply(HttpResponse::body);
sync : 200 hello from server version=HTTP_1_1
header : X-Demo=yes
async : hello from server
Output from 03-http-client.txt. The client prefers HTTP/2 by default; this local server speaks plain HTTP/1.1, so the response reports HTTP_1_1. send blocks; sendAsync returns a CompletableFuture you can compose (see the CompletableFuture guide). Compared with HttpURLConnection, there is no connection-state juggling and no third-party dependency.
var in lambda parameters (JEP 323)
Java 10 allowedvar for local variables; Java 11 allowed it in lambda parameters. It looks pointless ((var a, var b) -> a + b says nothing that (a, b) -> a + b did not), and for plain lambdas it is. The reason it exists is annotations: you cannot put an annotation on an inferred parameter, but you can on var. Source: VarLambda.java.
BiFunction<Integer, Integer, Integer> add = (var a, var b) -> a + b;
BiFunction<String, String, String> join = (@NonNull var a, @NonNull var b) -> a + "-" + b;
(var a, var b) : 5
with annotation : x-y
04-var-lambda.txt has the output. One rule has a real compiler message: you cannot mix var and explicit types in the same parameter list (07-compile-errors.txt):
broken/VarWithoutLambda.java:6: error: invalid lambda parameter declaration
(cannot mix 'var' and explicitly-typed parameters)
Run a source file directly (JEP 330)
With Java 11,java Hello.java compiles the file in memory and runs it, with no javac step and no .class file left behind. It is the quickest way to try something and is aimed at scripts and teaching. Source: SingleFile.java.
launched from source, java.version=11.0.32.1
That line is from 05-single-file.txt, produced by java src/SingleFile.java. The mode handles one file; multiple files need the normal compile step (later releases widened this).
Going deeper: nest-based access control (JEP 181)
Before 11, an inner class reading its outer class’s
private field forced the compiler to generate a hidden access$000-style bridge method. Java 11 introduced nests: the JVM itself lets nest mates touch each other’s private members. The demo counts bridge methods on the outer class, expecting none. Source: NestMates.java; output in 06-nest-mates.txt:nest host : NestMates
inner can read : 42
access$ methods on outer: 0
Practical effect: slightly smaller class files and reflection that finally agrees with the language (Class.getNestHost() reports the nest).
What broke: the Java EE and CORBA modules are gone (JEP 320)
This is the part of the Java 8 to 11 move that costs people an afternoon. Java 9 had already putjava.xml.bind (JAXB), java.xml.ws (JAX-WS), java.activation, java.corba and friends behind a “deprecated for removal” flag. Java 11 deleted them (JEP 320). Code that used javax.xml.bind.JAXBContext compiled on Java 8 with no dependency at all, because the class shipped inside the JDK. On 11 it does not. The same file, compiled by both JDKs (JaxbRemoved.java):
$ javac broken/JaxbRemoved.java (1.8.0_504)
(compiled cleanly)
$ javac broken/JaxbRemoved.java (11.0.32.1)
broken/JaxbRemoved.java:1: error: package javax.xml.bind does not exist
import javax.xml.bind.JAXBContext;
broken/JaxbRemoved.java:6: error: cannot find symbol
2 errors
Transcript: 07-compile-errors.txt. The error is “package does not exist”, not “module removed”, which is why it looks like a typo at first. The fix is to add the library as an ordinary dependency. If you want to keep the javax.xml.bind package name, use Jakarta XML Binding 2.3.x (jakarta.xml.bind:jakarta.xml.bind-api plus a runtime such as org.glassfish.jaxb:jaxb-runtime); versions 3.0 and later use the jakarta.xml.bind package instead, so imports change too.
The same trap hides in other places.javax.annotation.PostConstruct(fromjava.xml.ws.annotation),javax.activation.DataSource, andjavax.transactionare all in the removed set. If a Java 8 project fails to compile on 11 with “package javax.… does not exist”, check this list first.
Going deeper: every JEP in JDK 11
The JDK 11 project page lists these 17 JEPs:
- 181 Nest-Based Access Control; 309 Dynamic Class-File Constants; 315 Improve Aarch64 Intrinsics
- 318 Epsilon: A No-Op Garbage Collector (useful for allocation-free benchmarks)
- 320 Remove the Java EE and CORBA Modules
- 321 HTTP Client (Standard); 323 Local-Variable Syntax for Lambda Parameters; 330 Launch Single-File Source-Code Programs
- 324 Key Agreement with Curve25519 and Curve448; 329 ChaCha20 and Poly1305; 332 TLS 1.3
- 327 Unicode 10; 328 Flight Recorder; 331 Low-Overhead Heap Profiling
- 333 ZGC: A Scalable Low-Latency Garbage Collector (Experimental)
- 335 Deprecate the Nashorn JavaScript Engine; 336 Deprecate the Pack200 Tools and API
Common mistakes moving from Java 8 to 11
Assuming JAXB, JAX-WS or javax.annotation is still in the JDK
It is not. Add the Jakarta artifacts as dependencies, as shown above. This is the most common Java 8 to 11 build failure.
Using trim() to test for blank input
trim() ignores Unicode whitespace such as the EM SPACE, as the output above shows. Use isBlank() or strip() when the input may contain non-ASCII whitespace.Using var where the type is not obvious
var is a readability tool, not a typing saver. var result = service.process(x); hides the type from the reader. Use it when the right-hand side already names the type.Using readString on large files
It reads the whole file into one String. For large files, stream the lines instead.
Mixing var and explicit types in one lambda
The compiler rejects it with “invalid lambda parameter declaration”; use
var for every parameter or for none.Common interview questions on Java 11
What are the new features in Java 11 compared with Java 8?
Local-variable type inference with
var (Java 10) including in lambda parameters (11), new String methods, Files.readString/writeString, the standard HTTP Client, single-file source launch, nest-based access control, TLS 1.3, Flight Recorder and the Epsilon and experimental ZGC collectors. The Java EE and CORBA modules were removed.Difference between trim() and strip()?
trim() removes characters up to U+0020; strip() removes all Unicode whitespace (Character.isWhitespace). The EM SPACE demo above shows trim() leaving nine characters and strip() leaving five.Difference between isEmpty() and isBlank()?
isEmpty() is true only for length zero. isBlank() is also true for a string of only whitespace: " ".isBlank() is true, " ".isEmpty() is false.Why would you use var in a lambda parameter?
To attach annotations (
(@NonNull var a, @NonNull var b) -> ...) while keeping the type inferred. Without annotations there is no benefit over omitting the types. All parameters in one lambda must either use var or none.What did Java 11 remove?
The Java EE and CORBA modules (JEP 320): JAXB, JAX-WS, JAF,
javax.annotation, CORBA and java.transaction. They are available as separate Jakarta artifacts.How is the Java 11 HttpClient better than HttpURLConnection?
It supports HTTP/2, has a fluent builder API, provides both blocking
send and non-blocking sendAsync (returning CompletableFuture), and is immutable and thread-safe once built.How do you run a Java file without compiling it first?
java Hello.java (JEP 330). The source is compiled in memory; the first top-level class in the file must declare main.What is nest-based access control?
A JVM-level concept (JEP 181) that lets classes in the same nest (an outer class and its inner classes) access each other’s private members without compiler-generated bridge methods.
FAQ
Is Java 11 an LTS release?
Why does my Java 8 code fail to compile on Java 11?
The most common cause is a missing
javax.xml.bind, javax.annotation or similar package, because JEP 320 removed those modules. Add the matching Jakarta dependency.Can I use var for fields and method parameters?
No.
var works for local variables, for loop variables and lambda parameters only.Does Java 11 have records and text blocks?
No. Text blocks and records arrived in Java 15 and 16 respectively; see the Java 17 features guide.
Should you target Java 11 today? Only for an existing codebase that is already there. For anything new, jump to a current LTS: the language gains from 12 to 17 (records, switch expressions, text blocks, sealed classes) are covered in the Java 17 guide, and the upgrade path is in the migration guide. If you are coming from the other direction, Java 8 features is the prerequisite.
Further reading
- Companion code: java11-features (sources, compile-error cases and every captured output).
- On ankurm.com: Java 8 features, immutable collections (
List.of), Java strings deep dive, 30 Java string programs for interviews, CompletableFuture guide. - Official: JDK 11 on openjdk.org, JEP 320, JEP 321, JEP 330.
No Comments yet!