Core Java

New Features in Java 11

Java 11, released in 2018, introduced several features and enhancements. Let us delve into Java 11 new features.

1. Java 11 String API Additions

Java 11 introduces several enhancements to the String API, providing developers with more flexibility and functionality. Let’s delve into some notable additions:

1.1 String::repeat()

The repeat() method simplifies string repetition. For example:

String repeatedString = "Hello, ".repeat(3); 

// Results in "Hello, Hello, Hello, "

1.2 String::isBlank()

The isBlank() method checks if a string is empty or contains only whitespace:

boolean isEmpty = "   ".isBlank(); 

// Results in true

1.3 String::lines()

The lines() method returns a stream of lines extracted from the string:

String multilineString = "Line 1\nLine 2\nLine 3";

List<String> lines = multilineString.lines().collect(Collectors.toList());

2. Java 11 Local Variable Syntax for Lambda Parameters

Java 11 introduces a convenient feature that enhances the readability of lambda expressions by allowing the use of var as a parameter type. This addition simplifies code and reduces verbosity. With the introduction of local-variable type inference in Java 10, you can use the var keyword to declare local variables with inferred types. Java 11 extends this capability to lambda parameters.

(var param1, var param2) -> {
// Lambda body
}

Consider a simple example where we have a list of integers and want to iterate through it using a lambda expression:

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);

// Before Java 11
numbers.forEach((Integer number) -> {
System.out.println("Number: " + number);
});

// With Java 11
numbers.forEach((var number) -> {
System.out.println("Number: " + number);
});

The var keyword eliminates redundancy by inferring the type of the parameter, making the code more concise and readable. Utilizing var for lambda parameters provides several advantages:

  • Improved code readability.
  • Reduced boilerplate code.
  • Enhanced focus on the logic within the lambda body.

3. Java 11 New File Methods

Java 11 introduces several new methods in the java.nio.file package, providing enhanced functionality for working with files and directories. Let’s explore some of these valuable additions:

3.1 Files::readString

The readString method simplifies reading the contents of a file into a string:

Path filePath = Paths.get("example.txt");
String content = Files.readString(filePath, StandardCharsets.UTF_8);

3.2 Files::writeString

The writeString method enables writing a string to a file in a concise manner:

Path filePath = Paths.get("example.txt");
String content = "Hello, Java 11!";
Files.writeString(filePath, content, StandardCharsets.UTF_8);

3.3 Files::isSameFile

The isSameFile method checks if two paths refer to the same file:

Path path1 = Paths.get("file1.txt");
Path path2 = Paths.get("file2.txt");
boolean isSame = Files.isSameFile(path1, path2);

3.4 Files::mismatch

The mismatch method finds and returns the position of the first differing byte in two files:

Path file1 = Paths.get("file1.txt");
Path file2 = Paths.get("file2.txt");
long position = Files.mismatch(file1, file2);

4. Negate a Predicate Method Reference with Java 11

In Java 11, you can negate a Predicate method reference using the negate() method. Here’s an example illustrating how to negate a Predicate method reference:

package com.java11.example;

import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;

public class NegatePredicateExample {

    public static void main(String[] args) {
        // Create a list of integers
        List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);

        // Define a Predicate using a method reference
        Predicate<Integer> isEven = NegatePredicateExample::isEven;

        // Use the Predicate directly
        System.out.println("Even numbers: " + filterNumbers(numbers, isEven));

        // Negate the Predicate using negate()
        Predicate<Integer> isOdd = isEven.negate();
        System.out.println("Odd numbers: " + filterNumbers(numbers, isOdd));
    }

    // Method for Predicate method reference
    private static boolean isEven(int number) {
        return number % 2 == 0;
    }

    // Method to filter numbers based on a Predicate
    private static List<Integer> filterNumbers(List<Integer> numbers, Predicate<Integer> predicate) {
        return numbers.stream()
                .filter(predicate)
                .toList();
    }
}

In this example, we define a Predicate called isEven using the method reference NegatePredicateExample::isEven. Then, we use this Predicate to filter even numbers from a list. Next, we negate the Predicate using the negate() method and create a new Predicate called isOdd. Finally, we use the negated Predicate to filter odd numbers from the same list. Note that the negate() method is available in the Predicate interface starting from Java 11. This allows you to easily reverse the logic of a Predicate, making your code more expressive and readable.

5. HTTP Client

Java 11 introduced a modern and standardized HTTP client as part of the java.net.http package, providing a flexible and efficient way to send HTTP requests and process responses.

5.1 Creating an HTTP client

HttpClient httpClient = HttpClient.newHttpClient();

5.2 Making a Simple GET Request

HttpRequest request = HttpRequest.newBuilder()
  .uri(URI.create("https://api.example.com/data"))
  .build();

HttpResponse<String> response = httpClient.send(request, HttpResponse.BodyHandlers.ofString());

System.out.println("Response Code: " + response.statusCode());
System.out.println("Response Body: " + response.body());

5.3 Handling Asynchronous Requests

Executing asynchronous requests using CompletableFuture:

CompletableFuture<HttpResponse<String>> futureResponse = httpClient.sendAsync(request, HttpResponse.BodyHandlers.ofString());

futureResponse.thenAccept(response -> {
System.out.println("Async Response Code: " + response.statusCode());
System.out.println("Async Response Body: " + response.body());
});

5.4 Customizing Requests

Customizing requests with headers, timeouts, and more:

HttpRequest customRequest = HttpRequest.newBuilder()
  .uri(URI.create("https://api.example.com/data"))
  .header("Content-Type", "application/json")
  .timeout(Duration.ofSeconds(10))
  .GET()
  .build();

Java 11’s HTTP client simplifies HTTP communication, offering a modern alternative to the legacy HttpURLConnection. Its asynchronous capabilities and clean API design make it a powerful tool for handling HTTP requests in contemporary Java applications.

6. Performance Improvements

Java 11 brings several enhancements to improve the performance of Java applications, optimizing execution and responsiveness. Let’s explore some key performance improvements introduced in this version:

  • Epsilon Garbage Collector: Java 11 introduces the Epsilon garbage collector, a no-op garbage collector designed for scenarios where low latency and heap size are more critical than managing memory. It is particularly useful for performance testing and short-lived applications where garbage collection overhead is not a concern.
  • ZGC (Experimental): The Z Garbage Collector (ZGC) becomes available as an experimental feature in Java 11. ZGC is designed to provide low-latency performance by minimizing pause times, making it suitable for large heap applications. It aims to keep pause times within a specified limit, even for very large heaps, making it a favorable choice for applications with strict latency requirements.
  • Flight Recorder (JEP 328): Java Flight Recorder (JFR) is now available in OpenJDK builds by default in Java 11. JFR is a powerful tool for profiling and analyzing the behavior of applications in real time. It provides detailed insights into the performance characteristics of the application, allowing developers to identify bottlenecks and optimize code efficiently.
  • Nashorn JavaScript Engine Deprecation: While not a direct performance improvement, the deprecation of the Nashorn JavaScript engine in Java 11 can impact performance indirectly. With the deprecation, developers are encouraged to use alternative and more performant JavaScript engines, such as GraalVM’s JavaScript engine, providing better overall performance for Java applications with embedded JavaScript code.

7. Removed and Deprecated Modules

Here are some of the modules deprecated or removed in Java 11:

  • java.xml.ws (JAX-WS) – Deprecated in Java 11 and removed in a later release. Users are encouraged to migrate to Jakarta XML Web Services.
  • java.corba – Removed in Java 11. CORBA support is considered outdated, and alternative technologies are recommended.
  • java.transaction – Removed in Java 11. The Java EE-like transaction manager is no longer considered necessary in the context of modern Java SE applications.
  • java.xml.bind – Deprecated in Java 9 and removed in Java 11. Users are encouraged to migrate to Jakarta XML Binding (MOXy) or other alternatives.

8. Nest-Based Access Control

Nest-Based Access Control is designed to improve the encapsulation of classes in the same nest. A nest, in the context of Java, is a group of classes that share access to each other’s private members. This can lead to cleaner and more secure code.

  • Nest Host: The class that declares itself as a host for other classes in the nest.
  • Nest Members: Classes that are part of the nest and share access to each other’s private members.
  • Private Lookup: Nest members can use private lookup to access each other’s private members.

Let’s look at a simple example to understand how Nest-Based Access Control works in practice.

public class NestHost {
  private int privateField = 42;

  public class NestMember {
    public void accessPrivateField() {
      int value = NestHost.this.privateField;
      System.out.println("Accessing private field: " + value);
    }
  }
}

In this example, NestHost is the nest host, and NestMember is a nest member. The nest member can access the private field of the nest host using the NestHost.this syntax.

9. Conclusion

Java 11 stands as a significant milestone in the ever-evolving landscape of Java programming. Packed with a multitude of features, enhancements, and improvements, it reinforces Java’s commitment to adaptability, security, and developer productivity. The release not only addresses modern development challenges but also sets the stage for future innovation.
One of the standout features of Java 11 is the introduction of Nest-Based Access Control, a powerful mechanism that refines the encapsulation of classes within a nest. This not only promotes cleaner code but also enhances the security and structure of Java applications. By facilitating controlled access to private members within a nest, Java 11 empowers developers to create more robust and maintainable software.
Beyond Nest-Based Access Control, Java 11 includes updates to the standard library, improved performance, and extended support for modern standards. The removal of outdated modules and deprecation of certain features demonstrates Oracle’s commitment to maintaining a streamlined and efficient platform.
As developers embrace the capabilities of Java 11, they open doors to new possibilities in terms of language features, APIs, and tools. The Java community, known for its vibrancy and collaborative spirit, continues to contribute to the growth and enhancement of the language. Whether it’s the module system, local-variable syntax, or other language improvements, Java 11 caters to the evolving needs of developers and enterprises.

Yatin

An experience full-stack engineer well versed with Core Java, Spring/Springboot, MVC, Security, AOP, Frontend (Angular & React), and cloud technologies (such as AWS, GCP, Jenkins, Docker, K8).
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Inline Feedbacks
View all comments
Back to top button