diff --git a/LICENSE b/LICENSE
index 58e794c6..cc53a543 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,6 +1,6 @@
The MIT License (MIT)
-Copyright (c) 2016 Benjamin Winterberg
+Copyright (c) 2023 Benjamin Winterberg
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
diff --git a/README.md b/README.md
index 7ee572f3..e9caeed4 100644
--- a/README.md
+++ b/README.md
@@ -1,10 +1,17 @@
# Modern Java - A Guide to Java 8
+_This article was originally posted on [my blog](http://winterbe.com/posts/2014/03/16/java-8-tutorial/)._
-> [“Java is still not dead—and people are starting to figure that out.”](https://twitter.com/mreinhold/status/429603588525281280)
+> **You should also read my [Java 11 Tutorial](https://winterbe.com/posts/2018/09/24/java-11-tutorial/) (including new language and API features from Java 9, 10 and 11).**
Welcome to my introduction to [Java 8](https://jdk8.java.net/). This tutorial guides you step by step through all new language features. Backed by short and simple code samples you'll learn how to use default interface methods, lambda expressions, method references and repeatable annotations. At the end of the article you'll be familiar with the most recent [API](http://download.java.net/jdk8/docs/api/) changes like streams, functional interfaces, map extensions and the new Date API. **No walls of text, just a bunch of commented code snippets. Enjoy!**
-This article was originally posted on [my blog](http://winterbe.com/posts/2014/03/16/java-8-tutorial/). You should [follow me on Twitter](https://twitter.com/winterbe_).
+---
+
+
+ ★★★ Like this project? Leave a star, follow on Twitter or donate to support my work. Thanks! ★★★
+
+
+---
## Table of Contents
@@ -167,7 +174,7 @@ String converted = converter.convert("Java");
System.out.println(converted); // "J"
```
-Let's see how the `::` keyword works for constructors. First we define an example bean with different constructors:
+Let's see how the `::` keyword works for constructors. First we define an example class with different constructors:
```java
class Person {
@@ -357,7 +364,7 @@ optional.ifPresent((s) -> System.out.println(s.charAt(0))); // "b"
A `java.util.Stream` represents a sequence of elements on which one or more operations can be performed. Stream operations are either _intermediate_ or _terminal_. While terminal operations return a result of a certain type, intermediate operations return the stream itself so you can chain multiple method calls in a row. Streams are created on a source, e.g. a `java.util.Collection` like lists or sets (maps are not supported). Stream operations can either be executed sequentially or parallely.
-> You should also check out [Stream.js](https://github.com/winterbe/streamjs), a JavaScript port of the Java 8 Streams API.
+> Streams are extremely powerful, so I wrote a separate [Java 8 Streams Tutorial](http://winterbe.com/posts/2014/07/31/java8-stream-tutorial-examples/). **You should also check out [Sequency](https://github.com/winterbe/sequency) as a similiar library for the web.**
Let's first look how sequential streams work. First we create a sample source in form of a list of strings:
diff --git a/src/com/winterbe/java11/HttpClientExamples.java b/src/com/winterbe/java11/HttpClientExamples.java
new file mode 100644
index 00000000..7342b1de
--- /dev/null
+++ b/src/com/winterbe/java11/HttpClientExamples.java
@@ -0,0 +1,78 @@
+package com.winterbe.java11;
+
+import java.io.IOException;
+import java.net.Authenticator;
+import java.net.PasswordAuthentication;
+import java.net.URI;
+import java.net.http.HttpClient;
+import java.net.http.HttpRequest;
+import java.net.http.HttpResponse;
+import java.time.Duration;
+
+public class HttpClientExamples {
+
+ public static void main(String[] args) throws IOException, InterruptedException {
+// syncRequest();
+// asyncRequest();
+// postData();
+ basicAuth();
+ }
+
+ private static void syncRequest() throws IOException, InterruptedException {
+ var request = HttpRequest.newBuilder()
+ .uri(URI.create("https://winterbe.com"))
+ .build();
+ var client = HttpClient.newHttpClient();
+ HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString());
+ System.out.println(response.body());
+ }
+
+ private static void asyncRequest() {
+ 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);
+ }
+
+ private static void postData() throws IOException, InterruptedException {
+ var request = HttpRequest.newBuilder()
+ .uri(URI.create("https://postman-echo.com/post"))
+ .timeout(Duration.ofSeconds(30))
+ .version(HttpClient.Version.HTTP_2)
+ .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()); // 200
+ }
+
+ private static void basicAuth() throws IOException, InterruptedException {
+ var client = HttpClient.newHttpClient();
+
+ var request1 = HttpRequest.newBuilder()
+ .uri(URI.create("https://postman-echo.com/basic-auth"))
+ .build();
+ var response1 = client.send(request1, HttpResponse.BodyHandlers.ofString());
+ System.out.println(response1.statusCode()); // 401
+
+ var authClient = HttpClient
+ .newBuilder()
+ .authenticator(new Authenticator() {
+ @Override
+ protected PasswordAuthentication getPasswordAuthentication() {
+ return new PasswordAuthentication("postman", "password".toCharArray());
+ }
+ })
+ .build();
+ var request2 = HttpRequest.newBuilder()
+ .uri(URI.create("https://postman-echo.com/basic-auth"))
+ .build();
+ var response2 = authClient.send(request2, HttpResponse.BodyHandlers.ofString());
+ System.out.println(response2.statusCode()); // 200
+ }
+
+}
diff --git a/src/com/winterbe/java11/LocalVariableSyntax.java b/src/com/winterbe/java11/LocalVariableSyntax.java
new file mode 100644
index 00000000..e2a60906
--- /dev/null
+++ b/src/com/winterbe/java11/LocalVariableSyntax.java
@@ -0,0 +1,37 @@
+package com.winterbe.java11;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.function.Predicate;
+
+public class LocalVariableSyntax {
+
+ public static void main(String[] args) {
+ var text = "Banana";
+// Incompatible types:
+// text = 1;
+
+
+// Cannot infer type:
+// var a;
+// var nothing = null;
+// var bla = () -> System.out.println("Hallo");
+// var method = LocalVariableSyntax::someMethod;
+
+ var list1 = new ArrayList<>(); // ArrayList