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 set 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 !25
• 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).
Lesson 2: Convenience factory
methods for collections
26. @mirocupak !26
• Good performance.
• Don’t create mutable collections unless necessary.
• More info: JEP 269: Convenience Factory Methods for Collections.
Lesson 2: 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 !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.
Lesson 3: Improved try-with-
resources
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
Explore how the pattern matching API plays nicely with streams.
Hint: Use Matcher to obtain all results of a match.
39. @mirocupak
Lesson 4: Stream API enhancements
!39
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 !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.
Lesson 4: Stream API enhancements
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 !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.
Lesson 5: Extensions to Optional
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 !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.
Lesson 6: CompletableFuture 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 !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.
Lesson 7: Reactive streams
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 !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.
Lesson 8: Process API
67. @mirocupak !67
Task 9.1
Use the new HTTP/2 client API to execute a request against a server.
Read the response.
Lesson 9: HTTP/2 client
68. @mirocupak !68
Task 9.2
Use the new HTTP/2 client API to execute a request against a server
asynchronously. Read the response.
Lesson 9: HTTP/2 client
69. @mirocupak
Lesson 9: HTTP/2 client
!69
• 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.
• But aware it’s an incubator module.
• More info: JEP 110: HTTP 2 Client.
71. @mirocupak
Lesson 10: Local variable type inference
!71
• Does not replace static typing.
• Generally good.
• Reduces boilerplate and improves readability.
• Helps with maintenance and refactoring.
• Use for local variables with initializers (especially constructors) and for
loops.
• Can’t use for method formals, constructor formals, method return types,
fields, catch formals, null or array initializers, lambdas, method references,
or any other kind of variable declaration.
• Consider whether to use when the generated type is not obvious.
• But use for complex types when breaking chained or nested expressions
with local variables.
• Primitive types might surprise you, be careful (e.g. byte, short, long all
inferred as int).
72. @mirocupak !72
• Be very careful about combining with <> and generic methods (e.g. var list
= new ArrayList<>()).
• Probably not the best idea to use with anonymous classes.
• Use carefully chosen and expressive variable names.
• 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.
• Code to the interface pattern does not work, but that’s kind of OK.
• More info: JEP 286: Local-Variable Type Inference.
Lesson 10: Local variable type inference