I used JDK 1.8 in my previous work, and the new company uses Java 11 as the new development version. Many features of Java 11 are not understood, so this article will summarize the use of the new features in Java 11.
Local variable type inference
Java 10 introduces a new language keyword, var, that selectively replaces type information when declaring local variables.
This is how we used to declare variables before Java 10
String text = "Hello Java 8";Copy the code
Now you can replace String with var. The compiler deduces the correct type from the assignment of a variable. In this case, text is of type String.
var text = "Hello Java 10";Copy the code
Variables declared with var are still statically typed. You cannot reassign Incompatible types to these variables. This code fragment cannot compile
var text = "Hello Java 11"; text = 23; // Incompatible typesCopy the code
You can also use final and var together to disallow reassignment of a variable with another value
final var text = "Banana";
text = "Joe"; // Cannot assign a value to final variable 'text'Copy the code
Similarly, var is not allowed when the compiler cannot infer the correct type of a variable. All of the following code examples cause compiler errors
// Cannot infer type: var a; var nothing = null; var lambda = () -> System.out.println("Pity!" ); var method = this::someMethod;Copy the code
Local variable type inference is excellent with generics. In the next example, current has a fairly detailed type Map<String, List<Integer>> that can be simplified to a var keyword, saving you a lot of boilerplate code
var myList = new ArrayList<Map<String, List<Integer>>>();
for (var current : myList) {
// current is infered to type: Map<String, List<Integer>>
System.out.println(current);
}Copy the code
Starting with Java 11, the var keyword is also allowed for lambda arguments, which enables you to add comments to them
Predicate<String> predicate = (@Nullable var a) -> true;Copy the code
HttpClient
Java 9 introduces a new, mooted HttpClient API to handle HTTP requests. As of Java 11, this API is now in final form and is available in the standard library package Java.net. Let’s experiment with what this API can do.
The new HttpClient can be used synchronously or asynchronously. A synchronous request blocks the current thread until the response is available. BodyHandlers define the expected body type of the response (such as a string, byte array, or file).
var request = HttpRequest.newBuilder()
.uri(URI.create("https://winterbe.com"))
.GET()
.build();
var client = HttpClient.newHttpClient();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());Copy the code
The same request can be executed asynchronously. Calling sendAsync does not block the current thread, but returns a CompletableFuture to build the asynchronous operation pipeline.
var request = HttpRequest.newBuilder()
.uri(URI.create("https://winterbe.com"))
.build();
var client = HttpClient.newHttpClient();
client.sendAsync(request, HttpResponse.BodyHandlers.ofString())
.thenApply(HttpResponse::body)
.thenAccept(System.out::println);Copy the code
The next example is sending data to a given URL via POST. Like BodyHandlers, you use BodyPublisher to define the types of data you want to send as the body of a request, such as strings, byte arrays, files, or input streams.
var request = HttpRequest.newBuilder() .uri(URI.create("https://postman-echo.com/post")) .header("Content-Type", "text/plain") .POST(HttpRequest.BodyPublishers.ofString("Hi there!" )) .build(); var client = HttpClient.newHttpClient(); var response = client.send(request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.statusCode()); / / 200Copy the code
The final example shows how to perform authorization through basic-Auth
var request = HttpRequest.newBuilder() .uri(URI.create("https://postman-echo.com/basic-auth")) .build(); var client = HttpClient.newBuilder() .authenticator(new Authenticator() { @Override protected PasswordAuthentication getPasswordAuthentication() { return new PasswordAuthentication("postman", "password".toCharArray()); } }) .build(); var response = client.send(request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.statusCode()); / / 200Copy the code
A collection of Collections
Collections such as Lists, sets, and maps have been extended in new ways. List.of creates a new immutable List with the given parameters. List.copyOf creates an immutable copyOf the List.
var list = List.of("A", "B", "C");
var copy = List.copyOf(list);
System.out.println(list == copy); // trueCopy the code
Since the list is already immutable, it is not really necessary to create a copy of the list instance, so list and copy are the same instance. However, if you copy a mutable list, the copied instance is different from the original.
var list = new ArrayList<String>();
var copy = List.copyOf(list);
System.out.println(list == copy); // falseCopy the code
When creating immutable mappings, you don’t have to create the mapping items yourself, but pass keys and values as alternate parameters
var map = Map.of("A", 1, "B", 2);
System.out.println(map); // {B=2, A=1}
Copy the code
The data flow Streams
Flows were introduced in Java 8, with three new methods now added. OfNullable constructs a Stream from a single element:
Stream.ofNullable(null)
.count() // 0Copy the code
Both the dropWhile and takeWhile methods accept a predicate to decide which elements to discard or select from the stream
Stream.of(1, 2, 3, 2, 1) .dropWhile(n -> n < 3) .collect(Collectors.toList()); // [3, 2, 1] Stream.of(1, 2, 3, 2, 1) .takeWhile(n -> n < 3) .collect(Collectors.toList()); / / [1, 2]Copy the code
If you’re not familiar with Streams, check out another article I wrote about using Java streams.
Optionals
Optionals adds very handy new methods, for example, you can now simply convert an Optionals to a stream, or provide another Optionals as a callback to an empty Optionals
Optional.of("foo").orElseThrow(); // foo
Optional.of("foo").stream().count(); // 1
Optional.ofNullable(null)
.or(() -> Optional.of("fallback"))
.get(); Copy the code
Strings
String, one of the most basic classes, adds helper methods for trimming trimming or checking for whitespace, as well as converting strings to streams.
" ".isBlank(); // true " Foo Bar ".strip(); // "Foo Bar" " Foo Bar ".stripTrailing(); // " Foo Bar" " Foo Bar ".stripLeading(); // "Foo Bar " "Java".repeat(3); // "JavaJavaJava" "A\nB\nC".lines().count(); / / 3Copy the code
InputStreams
InputStream adds a super useful method for transferring data to OutputStream, which is a very common use case when dealing with raw data streams.
var classLoader = ClassLoader.getSystemClassLoader();
var inputStream = classLoader.getResourceAsStream("myFile.txt");
var tempFile = File.createTempFile("myFileCopy", "txt");
try (var outputStream = new FileOutputStream(tempFile)) {
inputStream.transferTo(outputStream);
}Copy the code
The resources
- Java 11 Tutorial