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