8. @mirocupak
Lesson 1: JShell
8
Task 1.3
Call a method that might throw a (checked) exception. How is it handled?
What happens when an exception is thrown? How is a location in JShell
referenced in a stacktrace?
14. @mirocupak
Lesson 1: JShell
14
Task 1.9
Save your current snippets, restart JShell, and load the snippets you
saved. Save all the commands and snippets for later use.
17. @mirocupak
Lesson 1: JShell
17
Task 1.12
Use JShell to explore its own API. Use the API to process a snippet of your
choice and read the results.
18. @mirocupak
Lesson 1: JShell
18
• Useful tool for whenever you need to try out something small quickly.
• Not a debugging tool.
• Prefer IDEs for any larger tasks.
• Use /help for more information about commands.
• Configure your own editor.
• More info: JEP 222: jshell: The Java Shell (Read-Eval-Print Loop).
20. @mirocupak
Lesson 2: Convenience factory methods for collections
20
Task 2.1
How would you create an immutable list in Java 8? What are the problems
with this approach? Are there any alternatives?
21. @mirocupak
Lesson 2: Convenience factory methods for collections
21
Task 2.2
What is the type of the return value of the of method?
22. @mirocupak
Lesson 2: Convenience factory methods for collections
22
Task 2.3
What’s the API for creating immutable collections for Set and Map? Does it
differ from List?
23. @mirocupak
Lesson 2: Convenience factory methods for collections
23
Task 2.4
What’s the API for creating immutable copies of collections for a Map? How
does it differ from the respective API in List and Set?
24. @mirocupak
Lesson 2: Convenience factory methods for collections
24
Task 2.5
How do you get the output of a stream into an immutable collection?
25. @mirocupak
Lesson 2: Convenience factory methods for collections
25
Task 2.6
What’s the most concise way of converting a collection into an array?
26. @mirocupak
Lesson 2: Convenience factory methods for collections
26
• Obtain immutable collections via of/ofEntries methods.
• Create immutable copies of collections via copyOf (Java 10).
• Static import java.util.Map.entry.
• Less verbose, no static initializer blocks.
• Don’t use Arrays.asList or Stream.of as shortcuts for creating collections.
• Don’t use external libraries if you only need immutable collections (Guava).
• No need to worry about leaving references to underlying collections.
• Thread-safe and can be shared freely (no need for defensive copies).
• Good performance.
• Don’t create mutable collections unless necessary.
• More info: JEP 269: Convenience Factory Methods for Collections.
28. @mirocupak
Lesson 3: Improved try-with-resources
28
Task 3.1
Read a file from disk to standard output (copy to standard output). Make
sure you clean up the resources as needed.
29. @mirocupak
Lesson 3: Improved try-with-resources
29
Task 3.2
Refactor your previous example to take advantage of effectively final
variables.
30. @mirocupak
Lesson 3: Improved try-with-resources
30
Task 3.3
Can we make the code even simpler?
Hint: Check out the InputStream API for useful methods.
31. @mirocupak
Lesson 3: Improved try-with-resources
31
• Always prefer try-with-resources, don’t use try-finally and definitely don’t use finalizers to close resources.
• Be aware of convenience methods, such as InputStream.transferTo.
• Don’t create unnecessary helper objects.
• More info: JEP 213: Milling Project Coin.
33. @mirocupak
Lesson 4: Stream API enhancements
33
Task 4.1
Modify the stream below to only print the numbers <5 (>5).
IntStream.range(0,10).forEach(System.out::println)
34. @mirocupak
Lesson 4: Stream API enhancements
34
Task 4.2
Demonstrate a difference between filter and takeWhile
(dropWhile).
Hint: Print even numbers <100.
37. @mirocupak
Lesson 4: Stream API enhancements
37
Task 4.5
Suppose we have the following list of numbers:
List.of(2, 3, 4, 7, 9, 11)
Count the numbers >5 by parity.
Hint: filtering.
38. @mirocupak
Lesson 4: Stream API enhancements
38
Task 4.6
Compute average of elements in a stream.
Hint: teeing.
39. @mirocupak
Lesson 4: Stream API enhancements
39
Task 4.6
Explore how the pattern matching API plays nicely with streams.
Hint: Use Matcher to obtain all results of a match.
Task 4.7
Explore how the date-time API plays nicely with streams.
Hint: Use LocalDate to obtain list of dates between now and Christmas.
40. @mirocupak
Lesson 4: Stream API enhancements
40
• Be aware of new stream methods: takeWhile, dropWhile, iterate.
• Familiarize yourself with various collectors available out of the box.
• Prefer collecting into immutable collections using toUnmodifiableList, toUnmodifiableSet,
toUnmodifiableMap.
• Check for convenience stream methods before converting to streams manually (e.g. LocalDate,
Matcher).
• Avoid unnecessary null checks with ofNullable.
• Streams are suitable for more use cases now, but not all use cases.
• Don’t overuse streams as they can make code hard to read and difficult to maintain.
44. @mirocupak
Lesson 5: Extensions to Optional
44
Task 5.3
Another 2 methods in the same family were added in Java 10. Can you
find them?
45. @mirocupak
Lesson 5: Extensions to Optional
45
Task 5.4
Filter out empty values from a given collection of Optionals, e.g.:
List.of(Optional.of(1), Optional.empty(),
Optional.of(2))
Hint: flatMap.
46. @mirocupak
Lesson 5: Extensions to Optional
46
• Use ifPresentOrElse instead of if-isPresent construct.
• or provides a clean fluent way of chaining behaviour on Optionals.
• Be aware of orElse* methods, e.g. the new orElseThrow (Java 10).
• Use stream to take advantage of the lazy nature of streams and handle streams of Optionals.
• Remember that isPresent is rarely the answer.
48. @mirocupak
Lesson 6: CompletableFuture updates
48
Task 6.1
completeOnTimeout is great for completing a future normally based on
a timeout. How do I complete a future exceptionally based on a timeout?
49. @mirocupak
Lesson 6: CompletableFuture updates
49
Task 6.2
Inspect the contract of the copy method. Demonstrate the one-way
synchronization it provides.
50. @mirocupak
Lesson 6: CompletableFuture updates
50
Task 6.3
Take some time to explore other new additions to the
CompletableFuture API we haven’t talked about.
51. @mirocupak
Lesson 6: CompletableFuture updates
51
• With Java 9+, you can complete CompletableFutures normally and exceptionally based on a timeout
(completeOnTimeout, orTimeout).
• copy provides an easy method for building asynchronous APIs.
• It’s usually a good idea to make copies before exposing CompletableFuture in APIs.
• Be aware of the various utility methods in the CompletableFuture API.
• More info: JEP 266: More Concurrency Updates.
53. @mirocupak
Lesson 7: Reactive streams
53
Task 7.1
Implement a subscriber echoing messages from the publisher.
Hint: Request new message in onSubscribe and onNext.
54. @mirocupak
Lesson 7: Reactive streams
54
Task 7.2
What happens if we request 2 messages in onNext every time? How
about Long.MAX_VALUE?
59. @mirocupak
Lesson 7: Reactive streams
59
• The right approach for asynchronous stream processing with nonblocking back pressure.
• Don’t implement yourself, use a library.
• More info: JEP 266: More Concurrency Updates.
61. @mirocupak
Lesson 8: Process API
61
Task 8.1
Launch an external process from Java. What are the problems with this
API?
62. @mirocupak
Lesson 8: Process API
62
Task 8.2
List all the commands running in your OS visible to you.
Hint: allProcesses.
63. @mirocupak
Lesson 8: Process API
63
Task 8.3
Launch an external process that runs for 3 seconds. Print the PID of the
(now dead) process as soon as it finishes.
Hint: sleep 3.
64. @mirocupak
Lesson 8: Process API
64
Task 8.4
List your currently running Java processes with jps. Use grep to find
JShell in the list.
Hint: startPipeline.
65. @mirocupak
Lesson 8: Process API
65
• ProcessHandle is a clean way of obtaining information about processes.
• Don’t implement yourself. Don’t use MXBeans or OS utilities.
• Take advantage of convenience methods: pid, info, command…
• Trigger actions on process termination via onExit.
• Connect ProcessBuilder with ProcessHandle via toHandle.
• Create pipelines via ProcessBuilder.startPipeline.
• More info: JEP 102: Process API Updates.
67. @mirocupak
Lesson 9: HTTP/2 client
67
Task 9.1
Execute an HTTP request against a server the old-fashioned way
(HttpURLConnection API). Read the status code as well as the body of
the response.
68. @mirocupak
Lesson 9: HTTP/2 client
68
Task 9.2
Use the new HTTP/2 client API to execute a request against a server. Read
the response.
69. @mirocupak
Lesson 9: HTTP/2 client
69
Task 9.3
Use the new HTTP/2 client API to execute a request against a server
asynchronously. Read the response.
71. @mirocupak
Lesson 9: HTTP/2 client
71
• Clean separation: HttpClient, HttpRequest, HttpResponse.
• HttpURLConnection is not pleasant to use.
• Avoid APIs with side effects.
• The new client API is versatile, flexible and clean.
• Prefer functionality in the JDK to external libraries.
• More info: JEP 110: HTTP 2 Client.
73. @mirocupak
Lesson 10: Local variable type inference
73
• Does not replace static typing.
• Generally good - reduces boilerplate, improves readability, and helps with maintenance and refactoring.
• Use for local variables with initializers (especially constructors) and for loops.
• Use for complex types when breaking chained or nested expressions with local variables.
• Can’t use for declarations without explicit initialization, null or array initializers, compound declarations,
method signatures, class fields, catch formals, lambdas or method references.
• Consider whether to use when the generated type is not obvious.
• Primitive types might surprise you, be careful (e.g. byte, short, long all inferred as int).
• Code to the interface pattern does not work, but that’s kind of OK.
• Be very careful about combining with <> and generic methods (e.g. var list = new ArrayList<>()).
• Works with non-denotable types (e.g. intersection types), but be careful!
• Capture variables are projected to supertypes that do not mention capture variables.
74. @mirocupak
Lesson 10: Local variable type inference
74
• Probably not the best idea to use with anonymous classes.
• Use carefully chosen and expressive variable names.
• Don’t use var as names of variables, methods, enums (even if it works).
• Don’t use Hungarian notation.
• Don’t rely on IDEs.
• Minimize the scope of local variables.
• Declare variable when it’s first used.
• Declaration not containing an initializer (i.e. you can’t use var) often indicates the scope is not minimal.
• Prefer for loops to while loops.
• Keep methods small and focused.More info: JEP 286: Local-Variable Type Inference.