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 + + var list2 = new ArrayList>>(); + + for (var current : list2) { + // current is of type: Map> + System.out.println(current); + } + + Predicate predicate1 = (@Deprecated var a) -> false; + + } + + void someMethod() {} + +} diff --git a/src/com/winterbe/java11/Misc.java b/src/com/winterbe/java11/Misc.java new file mode 100644 index 00000000..e343dec7 --- /dev/null +++ b/src/com/winterbe/java11/Misc.java @@ -0,0 +1,69 @@ +package com.winterbe.java11; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +public class Misc { + + @Deprecated(forRemoval = true) + String foo; + + public static void main(String[] args) throws IOException { + collections(); + strings(); + optionals(); + inputStreams(); + streams(); + } + + private static void streams() { + System.out.println(Stream.ofNullable(null).count()); // 0 + System.out.println(Stream.of(1, 2, 3, 2, 1) + .dropWhile(n -> n < 3) + .collect(Collectors.toList())); // [3, 2, 1] + System.out.println(Stream.of(1, 2, 3, 2, 1) + .takeWhile(n -> n < 3) + .collect(Collectors.toList())); // [1, 2] + } + + private static void inputStreams() throws IOException { + var classLoader = ClassLoader.getSystemClassLoader(); + var inputStream = classLoader.getResourceAsStream("com/winterbe/java11/dummy.txt"); + var tempFile = File.createTempFile("dummy-copy", "txt"); + try (var outputStream = new FileOutputStream(tempFile)) { + inputStream.transferTo(outputStream); + } + System.out.println(tempFile.length()); + } + + private static void optionals() { + System.out.println(Optional.of("foo").orElseThrow()); // foo + System.out.println(Optional.ofNullable(null).or(() -> Optional.of("bar")).get()); // bar + System.out.println(Optional.of("foo").stream().count()); // 1 + } + + private static void strings() { + System.out.println(" ".isBlank()); + System.out.println(" Foo Bar ".strip()); // "Foo Bar" + System.out.println(" Foo Bar ".stripTrailing()); // " Foo Bar" + System.out.println(" Foo Bar ".stripLeading()); // "Foo Bar " + System.out.println("Java".repeat(3)); // "JavaJavaJava" + System.out.println("A\nB\nC".lines().count()); // 3 + } + + private static void collections() { + var list = List.of("A", "B", "C"); + var copy = List.copyOf(list); + System.out.println(list == copy); // true + + var map = Map.of("A", 1, "B", 2); + System.out.println(map); + } + +} diff --git a/src/com/winterbe/java11/dummy.txt b/src/com/winterbe/java11/dummy.txt new file mode 100644 index 00000000..5eced957 --- /dev/null +++ b/src/com/winterbe/java11/dummy.txt @@ -0,0 +1 @@ +Foobar \ No newline at end of file