In this detailed article , we will explore important Java 11 features with examples.
Introduction: Java 11 Features
Java 11 was released on September 25, 2018. It marked a significant release in the Java programming language and platform.The release of Java 11 brought several new features, improvements, and enhancements to the language and platform.
Let’s look into the important Java 11 features with examples.
Important Java 11 Features
Local-Variable Syntax for Lambda Parameters
Local-Variable Syntax for Lambda Parameters” is one the key Java 11 features . It allows you to use the var
keyword to declare the types of parameters in lambda expressions.
Let’s first look into the “Old way” of declaring lambda parameters with explicit types:
import java.util.function.BiFunction;
public class LambdaParameterExample {
public static void main(String[] args) {
// Old way: Explicitly declaring types
BiFunction<Integer, Integer, Integer> add = (Integer x, Integer y) -> x + y;
System.out.println("Using explicit types: " + add.apply(5, 3));
}
}
In this code, we’re using the BiFunction
functional interface to represent a lambda expression that takes two Integer
parameters and returns an Integer
result. The lambda parameters x
and y
are explicitly declared with their types as Integer
.
Now, let’s write the same thing using Java 11 var
keyword.
import java.util.function.BiFunction;
public class LambdaParameterExample {
public static void main(String[] args) {
// Old way: Explicitly declaring types
BiFunction<Integer, Integer, Integer> addOld = (Integer x, Integer y) -> x + y;
System.out.println("Using explicit types: " + addOld.apply(5, 3));
// New way: Using var for lambda parameters
BiFunction<Integer, Integer, Integer> addNew = (var x, var y) -> x + y;
System.out.println("Using 'var' keyword: " + addNew.apply(5, 3));
}
}
In this “New way,” with the feature introduced in Java 11, we use the var
keyword instead of explicitly declaring the types. Java infers the types of the lambda parameters based on the context and the expected types from the functional interface.
Asynchronous HTTP Client
Java 11 introduced a new, asynchronous HTTP client as a part of the java.net.http
package. It provides improved support for handling HTTP requests and responses, including asynchronous operations and HTTP/2 support. It as an alternative to the legacy HttpURLConnection
. It provides a more flexible and intuitive way to work with HTTP requests and responses.
Here’s an example of using the asynchronous HTTP client introduced in Java 11 to make asynchronous HTTP requests:
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.util.concurrent.CompletableFuture;
public class AsyncHttpClientExample {
public static void main(String[] args) {
HttpClient httpClient = HttpClient.newHttpClient();
// Create an asynchronous HTTP request
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://www.example.com"))
.build();
// Send the asynchronous request and handle the response asynchronously
CompletableFuture<HttpResponse<String>> responseFuture = httpClient.sendAsync(request, HttpResponse.BodyHandlers.ofString());
// Attach a callback to process the response when it's available
responseFuture.thenApplyAsync(response -> {
int statusCode = response.statusCode();
String responseBody = response.body();
System.out.println("Status Code: " + statusCode);
System.out.println("Response Body:\n" + responseBody);
return responseBody;
}).join(); // Wait for the response processing to complete
// Continue with other tasks...
}
}
In this example:
- We create an instance of
HttpClient
usingHttpClient.newHttpClient()
. - We create an
HttpRequest
object to specify the request details, including the URI. - We use
httpClient.sendAsync()
to send the asynchronous HTTP request. The response is obtained as aCompletableFuture<HttpResponse<String>>
. - We use
thenApplyAsync()
to attach a callback that processes the response when it becomes available. The callback extracts the status code and response body and prints them. - The
join()
method is used to wait for the asynchronous processing of the response to complete. This ensures that we don’t continue with other tasks before the response processing is done.
The asynchronous HTTP client in Java 11 provides a non-blocking way to perform HTTP requests and handle responses, making it suitable for scenarios where you want to avoid blocking the main thread while waiting for network operations.
Nest-Based Access Control
Nest-Based Access Control, introduced in Java 11, allows classes that are logically part of the same code entity to access each other’s private members without the need for explicit visibility modifiers. Here’s an example to demonstrate Nest-Based Access Control:
class Outer {
private int outerPrivate = 10;
class Inner {
private int innerPrivate = 20;
void accessOuterPrivate() {
System.out.println("Accessing outer private: " + outerPrivate);
}
}
}
public class NestAccessExample {
public static void main(String[] args) {
Outer outer = new Outer();
Outer.Inner inner = outer.new Inner();
inner.accessOuterPrivate(); // Access outer private member from inner class
}
}
In this example:
- The
Outer
class contains a private fieldouterPrivate
. - The
Inner
class is nested within theOuter
class and contains a private fieldinnerPrivate
. - The
Inner
class defines a methodaccessOuterPrivate()
that accesses the private fieldouterPrivate
from the enclosingOuter
class.
With Nest-Based Access Control, the Inner
class can directly access the private outerPrivate
member of the Outer
class without requiring explicit getter methods or changing the visibility of the field.
Epsilon: A No-Op Garbage Collector
Java 11 introduced the Epsilon garbage collector, which is intended for scenarios where you want to disable garbage collection entirely.
The primary use case for the Epsilon garbage collector is performance testing and benchmarking. When running performance tests or benchmarks, memory allocation and deallocation can introduce noise in the measurements, affecting the accuracy of the results. By using Epsilon, developers can eliminate the overhead of garbage collection during tests, enabling more accurate performance analysis of other parts of the application.
Here’s a brief example of how to enable and use the Epsilon garbage collector:
java -XX:+UnlockExperimentalVMOptions -XX:+UseEpsilonGC YourApplication
In this command, the -XX:+UnlockExperimentalVMOptions
flag allows you to use experimental VM options, and the -XX:+UseEpsilonGC
flag enables the Epsilon garbage collector.
Keep in mind that using Epsilon in production scenarios is not recommended, as it does not provide any memory reclamation and will lead to memory exhaustion if the application continuously allocates memory without releasing it.
Dynamic Class-File Constants
Dynamic Class-File Constants is a feature introduced in Java 11 that allows the Java Virtual Machine (JVM) to resolve constant values at runtime, enabling more flexible and efficient libraries. Here’s a brief example of how you might use dynamic class-file constants:
public class DynamicConstantsExample {
public static void main(String[] args) {
String dynamicMessage = ConstantsHolder.MESSAGE;
System.out.println(dynamicMessage);
}
}
class ConstantsHolder {
static {
System.out.println("Initializing ConstantsHolder");
}
public static final String MESSAGE = getDynamicMessage();
private static String getDynamicMessage() {
return "Hello, Dynamic Constants at " + System.currentTimeMillis();
}
}
In this example:
- The
ConstantsHolder
class contains a static initialization block that prints “Initializing ConstantsHolder” when the class is initialized. - The
MESSAGE
constant is defined aspublic static final String
, but its value is computed at runtime using thegetDynamicMessage()
method. - The
getDynamicMessage()
method generates a dynamic message containing the current timestamp. - In the
DynamicConstantsExample
class, we access theMESSAGE
constant fromConstantsHolder
and print its value.
When you run the DynamicConstantsExample
class, you’ll observe that the output includes the dynamically generated message along with the timestamp, reflecting the runtime value of the constant:
Initializing ConstantsHolder
Hello, Dynamic Constants at [current timestamp]
Single-File Source-Code Programs
Java 11 allows you to run a single-file source-code program without explicitly compiling it. You can use the java
command to run a .java
file directly.
Here’s a simple example of a single-file source-code program:
public class HelloSingleFile {
public static void main(String[] args) {
System.out.println("Hello, Single-File Source-Code Programs!");
}
}
Save the above code in a file named HelloSingleFile.java
. Open a terminal, navigate to the directory containing the file, and run the program using the command:
java HelloSingleFile.java
Output
Hello, Single-File Source-Code Programs!
It’s important to note that this feature is intended for short and simple programs. If your program becomes more complex or needs to be shared with others, it’s recommended to use traditional compilation and packaging methods.
Flight Recorder and Mission Control Open Sourced
Java Flight Recorder (JFR) and Java Mission Control (JMC) are tools introduced in Java 11 that provide developers with powerful capabilities for monitoring, profiling, and troubleshooting Java applications. They are designed to help developers optimize application performance, diagnose issues, and analyze the behavior of Java applications in real time.
Java Flight Recorder is a profiling and event collection framework built into the Java Virtual Machine (JVM). It collects detailed information about the runtime behavior of an application, including CPU usage, memory allocation, thread activity, garbage collection events, and more.
Java Mission Control(JMC) is a tool suite that provides a graphical interface for analyzing data collected by Java Flight Recorder. It offers a range of features to visualize, analyze, and optimize Java applications’ performance. JMC allows developers to monitor application behavior in real time and gather insights into the application’s resource usage, bottlenecks, and more.
Deprecating Java EE and CORBA Modules
Java EE (Enterprise Edition) and CORBA (Common Object Request Broker Architecture) modules were deprecated and subsequently removed from the Java SE platform starting with Java 11. This decision was part of Oracle’s efforts to simplify and modernize the Java platform and to align with the evolving needs of the Java community.
Improved Security and Performance in Java 11
Improvements in security and performance introduced in Java 11:
- TLS 1.3 Support: Added support for more secure and faster TLS 1.3 protocol.
- Enhanced Key Agreement: Added support for Curve25519 and Curve448 for secure key exchange.
- Security Enhancements: Improved cryptographic algorithms and security protocols.
- Single-File Programs: Run source-code programs without separate compilation for quicker testing.
- Performance Boosts: Optimized JVM startup times and memory usage.
- G1 Garbage Collector: Enhanced G1 collector for better performance and lower latency.
- ZGC and Epsilon: Introduced Z Garbage Collector and Epsilon GC for specialized memory management.
- JVM Improvements: New options for performance tuning and memory management.
Conclusion: Important Java 11 Features
In this comprehensive article, we explored the key Java 11 features with relevant examples. Hopefully, this will enable you to use these Java 11 features in your projects.