In Java 11, Oracle officially introduced support for the HTTP/2 protocol and a new HTTP client API known as
java.net.http.HttpClient
. This API is designed to replace older implementations such asHttpURLConnection
andApache HttpClient
, offering a more modern, user-friendly, and HTTP/2-compliant network communication tool.Here's an overview of key features of
java.net.http.HttpClient
in Java 11 with regard to HTTP/2 support:
-
HTTP/2 Support: By default,
HttpClient
supports HTTP/2, allowing the use of multiplexing, header compression, and other features that enhance network communication efficiency. -
Asynchronous API: Provides an asynchronous API, enabling the construction of non-blocking HTTP requests and better leveraging Java's asynchronous programming capabilities, such as
CompletableFuture
. -
Simplified API Design: Creating, sending HTTP requests, and handling responses have become more intuitive and straightforward, as demonstrated by the following example:
HttpClient httpClient = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create("https://example.com")) .header("Content-Type", "application/json") .POST(HttpRequest.BodyPublishers.ofString(jsonPayload)) .build(); HttpResponse
response = httpClient.send(request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.statusCode()); System.out.println(response.body()); -
Streaming Support: For large files or streaming responses, handlers like
BodyHandlers.ofInputStream()
can be used to avoid loading the entire response body into memory at once. -
Secure Connections: Supports TLS by default, making it easy to establish secure HTTPS connections and control SSL/TLS behavior through configuration options.
-
Modular Design: Since Java 9,
HttpClient
has been designed to be modular, allowing it to be directly integrated into applications without depending on external libraries.
Local type inference is a feature of the Java language introduced from Java 10 using the var
keyword, which allows developers to declare local variables without specifying their types explicitly. The compiler automatically infers the type based on the context.
Moreover, starting from Java 7, the introduction of the try-with-resources statement simplified resource management, ensuring resources are automatically closed after use, reducing the risk of resource leaks. For example:
try (FileInputStream fis = new FileInputStream("input.txt")) {
// Use fis to read the file...
} catch (IOException e) {
// Handle file reading exceptions
}
Immutable collections are a special type within the Java Collections Framework where the content cannot be changed after creation. Attempting to modify an immutable collection will result in an
UnsupportedOperationException
.
Since Java 9, interfaces can include private methods, adding flexibility and modularity to interface design.
Java 11 introduced several new methods to the String
class, such as isBlank()
, strip()
, repeat()
, and enhanced switch
expressions that allow pattern matching to simplify code.
The text block feature allows creating multiline strings using triple quotes, enhancing readability.
The JVM parameter -XX:+ShowCodeDetailsInExceptionMessages
enhances the detail level of exception messages, aiding in debugging.
Record types were introduced as a preview feature in Java 14 and became official in Java 15 onwards, simplifying the creation of data classes.
Sealed classes were introduced in Java 17, allowing developers to control which classes can extend a base class, thus better managing inheritance hierarchies. For example:
sealed class Animal permits Mammal, Bird, Reptile {
String name;
Animal(String name) {
this.name = name;
}
abstract void makeSound();
}
final class Mammal extends Animal {
Mammal(String name) {
super(name);
}
@Override
void makeSound() {
System.out.println("Woof!");
}
}
final class Bird extends Animal {
Bird(String name) {
super(name);
}
@Override
void makeSound() {
System.out.println("Tweet tweet!");
}
}
final class Reptile extends Animal {
Reptile(String name) {
super(name);
}
@Override
void makeSound() {
System.out.println("Hisss...");
}
}
public class Main {
public static void main(String[] args) {
Animal dog = new Mammal("Dog");
Animal sparrow = new Bird("Sparrow");
Animal snake = new Reptile("Snake");
// class InvalidAnimal extends Animal { ... }
dog.makeSound();
sparrow.makeSound();
snake.makeSound();
}
}
These features reflect the ongoing evolution of the Java language aimed at enhancing developer productivity and code quality.