Learn JDK11 with JShell (2018/12/15 JJUG CCC 2018 Fall)

# About me
- Naoki Kishida
- LINE Fukuoka
- Twitter: [@kis](https://twitter.com/kis)

<img src="https://qiita-image-store.s3.amazonaws.com/0/228058/5915a49b-3094-4488-7c59-e3d3f42e752a.jpeg">

----

# Agenda
- What is JShell (30 min)
- What's new in JDK11 (50 min)
- What's new in JDK12 (20 min)

total: 100 min

----
# What is JShell
---
# JShell
- REPL (Read-Eval-Print-Loop)
- Command line tool to evaluate a Java code snipets interactively
- Entering a programming element, we can get the result immediately

----
# JShell install and start
- Install JDK9+ and type `jshell` on a console
- My recommendation is to use JDK12ea
- http://jdk.java.net/12/

<img width="585" alt="スクリーンショット 2018-10-21 9.27.21.png" src="https://qiita-image-store.s3.amazonaws.com/0/228058/ea20b382-eb59-3397-a010-29a69bfe5f51.png">

----
# Haven't installed JDK11+ yet?
Web JShell console
https://tryjshell.org/
<img width="705" alt="スクリーンショット 2018-10-21 8.44.59.png" src="https://qiita-image-store.s3.amazonaws.com/0/228058/3a3bf9ba-8456-077c-93bb-53583a35150e.png">

----
# Restriction of TryJShell
JFrame is not allowed since TryJShell is a headless
<img width="937" alt="スクリーンショット 2018-10-21 8.45.33.png" src="https://qiita-image-store.s3.amazonaws.com/0/228058/8827f703-49a4-edef-b126-781891316f4d.png">

----
# /exit
- Exit JShell
- `/exi` `/ex` also are allowed

We can abbreviate a command while it is not ambiguous

```
jshell> /exit
|  Goodbye
~ $
```

----
# /help
- Show information
- To specify a command to show the detail

```
jshell> /he help
|  
|                                   /help
|                                   =====
|  
|  Display information about using the jshell tool.
...
```

----
# Expression
JShell returns a result of an expression you have entered.

```
jshell> 23 * 12
$1 ==> 276

jshell> Math.sqrt(2)
$2 ==> 1.4142135623730951
```

----
# Variable
You can define variables

```
jshell> String s = "Hello"
s ==> "Hello"

jshell> s
s ==> "Hello"
```

----
# var in JShell

`var` fits in well with JShell

```
jshell> var strs = List.of("aa", "bb")
strs ==> [aa, bb]
```

----
# Scratch variable

- Expression without a named variable will create a scratch variable
- Scratch variable is `$` + number form
- We can refer the value with the scratch variable

```
jshell> "hello"
$6 ==> "hello"

jshell> $6.toUpperCase()
$7 ==> "HELLO"
```

----
# /vars
Show declared variables

```
jshell> 23+4
$1 ==> 27

jshell> var a = "hello"
a ==> "hello"

jshell> /vars
|    int $1 = 27
|    String a = "hello"
```
----
# /vars
- can specify a variable name
- can specify a variable id

```
jshell> /vars a
|    String a = "hello"

jshell> /vars $1
|    int $1 = 27

jshell> /vars 1
|    int $1 = 27
```

----
# Change definitions

We can change definitions of a variable (or method, class) defined in JShell by entering new definition.

```
jshell> var s = "hello"
s ==> "hello"

jshell> /vars s
|    String s = "hello"

jshell> var s = 123
s ==> 123

jshell> /vars s
|    int s = 123
```

----
# Completion
[tab] to complete a method, class or variable

```
jshell> "abc".toU[tab]
```
↓

```
jshell> "abc".toUpperCase(
```

----
# Import completion
We can insert an import by [shift+tab], [i]

```
jshell> var f = new JFrame[shift+tab],[i]
```
↓

```
jshell> var f = new JFrame
0: Do nothing
1: import: javax.swing.JFrame
```
↓[1]

```
Choice: 
Imported: javax.swing.JFrame

jshell> var f = new JFrame
```

----
# Show a method signature and JavaDoc
[tab] to show the method signature after `(` at beginning of the method parameter
One more [tab] shows its JavaDoc

```
jshell> "abc".toUpperCase([tab]
Signatures:
String String.toUpperCase(Locale locale)
String String.toUpperCase()

<press tab again to see documentation>
```

----
# /imports
Show all imports

```
jshell> /i
|    import java.io.*
|    import java.math.*
|    import java.net.*
|    import java.nio.file.*
|    import java.util.*
|    import java.util.concurrent.*
|    import java.util.function.*
|    import java.util.prefs.*
|    import java.util.regex.*
|    import java.util.stream.*
|    import javax.swing.JFrame
```

----
# Default import
The imports below are imported by default

```
import java.io.*
import java.math.*
import java.net.*
import java.nio.file.*
import java.util.*
import java.util.concurrent.*
import java.util.function.*
import java.util.prefs.*
import java.util.regex.*
import java.util.stream.*
```

----
# JDK11
----
# JDK11
- New in JShell
- JEPs
- APIs

----
# What's new on JShell
Allow to open URL

- on startup

```
~ $ jshell https://kishida.github.io/misc/jframe.jshell
|  Welcome to JShell -- Version 12-ea
|  For an introduction type: /help intro
```

- on jshell command

```
jshell> /open https://kishida.github.io/misc/jframe.jshell
```

```java:kishida.github.io/misc/jframe.jshell
import javax.swing.*
var f = new JFrame("JShell")
f.setSize(400, 300)
f.setVisible(true)
```

<!--
<img width="998" alt="スクリーンショット 2018-10-20 10.18.39.png" src="https://qiita-image-store.s3.amazonaws.com/0/228058/8ee360d5-93fb-03f8-eb67-b75196710061.png">
-->

----

# JEPs
There are 16 JEPs in JDK11
<img width="300" alt="スクリーンショット 2018-10-20 9.39.39.png" src="https://qiita-image-store.s3.amazonaws.com/0/228058/66870647-541e-d873-c688-7c236ce56d51.png">

----
# Today's JEPs
- 321: HTTP Client(Standard)
- 181: Nest-Based Access Control
- 323: Local-Variable Syntax for Lambda Parameters
 
----
# 321: HTTP Client(Standard)
- Modern API
- HTTP2 support
- WebSocket
- Reactive

The new HTTP Client API in Java 11 [DEV5951]
Oct 23, 04:00 PM - 04:45 PM | Room 2004

----

# HTTP Client Component
- HttpClient
- HttpRequest
- HttpResponse
- BodyHandler
- BodySubscriber
- WebSocket
- and more...

----

# HTTP Client Basis
HTTP Client basic usage

```
var client = HttpClient.newHttpClient();
var request = HttpRequest.newBuilder()
        .uri(URI.create("http://openjdk.java.net/"))
        .build();
HttpResponse<String> res = client.send(
        request,
        HttpResponse.BodyHandlers.ofString());
System.out.println(res.statusCode());
System.out.println(res.body());
```

----
# HTTP Client step by step
- import java.net.http.*
- Prepare `HttpClient`
- Prepare `HttpRequest` with builder
- Send the request using the client
- `HttpResponse` will be returned
- Process the response

----
# import java.net.http.*
HTTP Client API is under `java.net.http` package

- java.net.http.HttpClient
- java.net.http.HttpRequest
- java.net.http/HttpResponse

```
jshell> import java.net.http.*

```
----
# Prepare `HttpClient`
Using a factory method `newHTtpClient()`

```
jshell> var client = HttpClient.newHttpClient()
client ==> jdk.internal.net.http.HttpClientImpl@5ad851c9(1)
```

----
# Configure `HttpClient`
Use a builder to configure `HttpClient`

```
jshell> import java.net.http.HttpClient.*

jshell> var client2 = HttpClient.newBuilder().
   ...> version(Version.HTTP_2).
   ...> followRedirects(Redirect.NORMAL).
   ...> build()
client2 ==> jdk.internal.net.http.HttpClientImpl@574b560f(1)
```

Terminate a line with `.` to span a snippet into multiple lines
or the expression will be evaluated as the `Builder`

----
# Prepare `HttpRequest` with builder

```
jshell> var request = HttpRequest.newBuilder(
   ...> URI.create("http://localhost:8080")).build()
request ==> http://localhost:8080 GET
```
Don't forget `build()` when receiving with `var`

----
# Configure `HttpRequest`
Use a builder to configure `HttpRequest`

```
jshell> var req2 = HttpRequest.newBuilder().
   ...> uri(URI.create("http://localhost:8080")).
   ...> timeout(java.time.Duration.ofMinutes(1)).
   ...> header("Content-Type", "application/x-www-form-urlencoded").
   ...> POST(HttpRequest.BodyPublishers.ofString(
   ...> "name=kishida&submit=ok")).
   ...> build()
req2 ==> http://localhost:8080 POST
```
Use `BodyPublisher` to send a post body

----
# Send the request by using the client

```
jshell> var response = client.send(request, BodyHandlers.ofString())
response ==> (GET http://localhost:8080) 200
```

Import the static class with [shift]+[tab], [i]

```
jshell> var response = client.send(request, BodyHandlers
0: Do nothing
1: import: java.net.http.HttpResponse.BodyHandlers
```

----
# `HttpResponse` will be returned
The type of the response is `HttpResponse` with a corresponding type to `BodyHandler` as a generic type

```
jshell> /v response
|    HttpResponse<String> response = (GET http://localhost:8080) 200
```
----
# Process the response
Getting the status code

```
jshell> response.statusCode()
$12 ==> 200
```

----
# Process the response
Getting the response body

```
shell> response.body().lines().limit(5).forEach(System.out::println)
<html><head><title>Hello</title></head>
<body><h1>Hello</h1>
This is server<br>2018-10-20T10:32:26.120379</body></html>
```
`lines()` is a new API of String on JDK11

----
# Asynchronous way
`sendAsync` returns `CompletableFuture` to process the request asynchronously

```
jshell> client.sendAsync(req, BodyHandlers.ofString())
$34 ==> jdk.internal.net.http.common.MinimalFuture@4e096385[Not completed] (id=100)

jshell> /vars $34
|    CompletableFuture<HttpResponse<String>> $34 = jdk.internal.net.http.common.MinimalFuture@4e096385[Completed normally] (id=100)
```
----
# Asyncronous way
`thenApply` or `thenAccept` to process a following procedures

```
jshell> $34.thenApply(HttpResponse::body)
$35 ==> jdk.internal.net.http.common.MinimalFuture@34f5090e[Completed normally] (id=143)

jshell> $35.thenAccept(System.out::println)
<html><head><title>Hello</title></head>
<body><h1>Hello</h1>
This is server<br>2018-10-22T12:20:52.580561</body></html>

$36 ==> jdk.internal.net.http.common.MinimalFuture@1cbb87f3[Completed normally] (id=144)
```

----
# 181: Nest-Based Access Control
Java has 4 visibilities

- public
- protected
- default
- private

But there is the 5th visibility

----
# 5th visibility
Nested private
We can use private members in a nestmates

```java
class Outer {
  class Inner {
    private static foo;
  }
  int foo() {
    return Inner.foo;
  }
}
```

----
# Nested is compiled into two independent class

- Outer.class
- Outer$Inner.class

Need to access Outer's private member from Outer$Inner
(Can't access Outer$Inner's private from even Outer)

----
# Secret method is generated until JDK 10

```
jshell> Outer.Inner.class.getDeclaredMethods()
$8 ==> Method[1] { static int Outer$Inner.access$000() }
```

----
# Peek Nestmates
Retrieving nestmates by `getNestMembers()`

```
jshell> HttpRequest.class.getNestMembers()
$18 ==> Class[4] {
 class java.net.http.HttpRequest,
 class java.net.http.HttpRequest$BodyPublishers,
 interface java.net.http.HttpRequest$BodyPublisher,
 interface java.net.http.HttpRequest$Builder }
```
----
# Peek Nestmates
Retrieving nest host by `getNestHost()`
nest host: top level type of the nestmates

```
jshell> HttpRequest.Builder.class.getNestHost()
$19 ==> class java.net.http.HttpRequest
```
----
# Peek Nestmates
Checking if a class is the nestmate
`HttpRequest` is a nestmate of `HttpRequest.Builder`

```
jshell> HttpRequest.class.isNestmateOf(HttpRequest.Builder.class)
$20 ==> true
```
`HttpRequest` is NOT a nestmate of `String`

```
jshell> HttpRequest.class.isNestmateOf(String.class)
$21 ==> false
```

----
# Try to check nestmates
Class of Collectoin.empty()

```
jshell> Collections.emptyList().getClass().getNestMembers()
```

----
# Try to check a defining class

```
jshell> class Outer { class Inner {} }
|  created class Outer

jshell> Outer.class.getNestMembers()
```

----
# Class defining in JShell
Class that is defined in JShell is defined as a nested class of the blank name class

```
jshell> Outer.class.getNestMembers()
$2 ==> Class[3] { class , class Outer, class Outer$Inner }
```
----
# 323: Local-Variable Syntax for Lambda Parameters
Allow to use `var` for lambda parameters

```java
(var x, var y) -> x + y
```

----
# Example

```
jshell> IntBinaryOperator op = (var x, var y) -> x + y
op ==> $Lambda$17/0x00000008000b2c40@1e88b3c
```

----
# Every parameter must be `var` when using `var`
Can not mix `var` and non `var`

```
jshell> IntBinaryOperator ibo = (var x, y) -> x + y
|  Error:
|  invalid lambda parameter declaration
|    (cannot mix 'var' and implicitly-typed parameters)
|  IntBinaryOperator ibo = (var x, y) -> x + y;
|                          ^
```

----
# Every parameter must be `var` when use `var`
Can not mix `var` and explicit type

```
jshell> IntBinaryOperator ibo = (var x, int y) -> x + y
|  Error:
|  invalid lambda parameter declaration
|    (cannot mix 'var' and explicitly-typed parameters)
|  IntBinaryOperator ibo = (var x, int y) -> x + y;
|                          ^
```

----
# Need parenthesis
What will occur with this?

```
jshell> IntFunction f = var x -> x * 2
```

----
# Need parenthesis
Need parenthesis even parameter is single

```
jshell> IntFunction f = var x -> x * 2
|  Error:
|  ';' expected
|  IntFunction f = var x -> x * 2;
|                     ^
```

Put parethesis

```
jshell> IntFunction f = (var x) -> x * 2
f ==> $Lambda$18/0x00000008000b7040@5e3a8624
```
----
# Is there anything good for using `var` on lambda parameters?
We can use annotation

```java
(@Nullable var s) -> s + "!!!"
```
🤔🤔🤔

----
# JDK11 APIs
- String
- I/O
- Util

----
# New in String
- `repeat(int)`
- `isBlank()`
- `strip()` / `stripLeading()` / `stripTrailing()`
- `lines()`
- `Character.toString(int)`

----
# repeat(int)
Repeat a string

```
jshell> "foo".repeat(3)
$38 ==> "foofoofoo"
```
----
# isBlank()
Same as `isEmpty()` but treating UTF-8 whitespace as space

```
jshell> var fullspace = "\u3000"
fullspace ==> "　"

jshell> fullspace.isEmpty()
$24 ==> false

jshell> fullspace.isBlank()
$25 ==> true
```

----
# strip() / stripLeading() / stripTrailing()
Same as `trim()`/ `trimLeft()` / `trimRight()` but treating UTF-8 whitespace as space

```
jshell> var s = fullspace + "ttt" + fullspace
s ==> "　ttt　"

jshell> s.trim()
$41 ==> "　ttt　"

jshell> s.strip()
$42 ==> "ttt"

jshell> s.stripLeading()
$43 ==> "ttt　"

jshell> s.stripTrailing()
$44 ==> "　ttt"
```

----
# lines()
Split a string to stream by `\n`

```
jshell> "abc\ndef\nghi".lines().count()
$18 ==> 3
```

----
# Character.toString(int)

```:JDK10
jshell> Character.toString(65)
|  Error:
|  incompatible types: possible lossy conversion from int to char
|  Character.toString(65)
|                     ^^
```

```:JDK11
jshell> Character.toString(65)
$15 ==> "A"
```

----
# New in I/O
- Path.of
- Files
- null I/O

----
# Path.of
`Paths.create` until JDK10
`Path.of` since JDK11
Follow the recent convention to use `of` to factory method

```
jshell> var p = Path.of("hello.txt")
p ==> hello.txt
```

----
# Files
- writeString
- readString

----
# Files.writeString
Write string to a file
`Files.writeString(Path, CharSequence, OpenOption...)`
`Files.writeString(Path, CharSequence, Charset, OpenOption...)`

```
jshell> Files.writeString(p, "Hello")
$4 ==> hello.txt
```

----
# Files.readStrig
Read a file content as string
`Files.readString(Path)`
`Files.readString(Path, Charset)`

```
jshell> Files.readString(p)
$5 ==> "Hello"
```

----
# null I/O
Input nothing, output nothing like `/dev/null`

- `Reader.nullReader()`
- `Writer.nullWriter()`
- `InputStream.nullInputStream()`
- `OutputStream.nullOutputStream()`

----
# null I/O example

```:Read
jshell> Reader.nullReader().read()
$13 ==> -1
```

```:Write
jshell> Writer.nullWriter().write("hello")

```
----
# New in java.util
- Collection.toArray(IntFunction)
- Predicate.not(Predicate)
- Optional.isEmpty()

----
# Collection.toArray(IntFunction)
Until JDK10, need to specify the array size or receive `Object` array

```:JDK10
jshell> var list = List.of("aa", "bb")
list ==> [aa, bb]

jshell> list.toArray(new String[list.size()])
$46 ==> String[2] { "aa", "bb" }

jshell> list.toArray()
$47 ==> Object[2] { "aa", "bb" }
```

----
# Collection.toArray(IntFunction)
We couldn't convert a list to a typed array with `toArray` on one-liner effectively

```
jshell> Collections.nCopies(new Random().nextInt(5), "a").toArray(new String[3]) 
$50 ==> String[4] { "a", "a", "a", "a" }
```

The prepared array is disposed

----
# Collection.toArray(IntFunction)
The new API resolve the problem

```:JDK11
jshell> list.toArray(String[]::new)
$48 ==> String[2] { "aa", "bb" }
```

----
# Predicate.not(Predicate)
We couldn't use a method reference when we need a negated condition so far

```
jshell> var strs = List.of("aa", "", "bb")
strs ==> [aa, , bb]

jshell> strs.stream().filter(s -> !s.isEmpty()).toArray()
$52 ==> Object[2] { "aa", "bb" }
```

----
# Predicate.not(Predicate)
We can negate a condition with method reference at JDK11

```
jshell> import static java.util.function.Predicate.not

jshell> strs.stream().filter(not(String::isEmpty)).toArray()
$55 ==> Object[2] { "aa", "bb" }
```

----
# Optional.isEmpty()
`Optional` has `isPresent()` so far
Negated condition `isEmpty()` is available on JDK11

```
jshell> Optional.empty().isEmpty()
$49 ==> true
```
`OptionalInt` and `OptionalDouble` have it also

----
# Other change
Changed the message of `ArrayIndexOutOfBoundsException`
We couldn't understand what does the number mean

```:JDK10
jshell> (new int[0])[0]
|  java.lang.ArrayIndexOutOfBoundsException thrown: 0
|        at (#1:1)
```

```:JDK11
jshell> (new int[0])[0]
|  Exception java.lang.ArrayIndexOutOfBoundsException: Index 0 out of bounds for length 0
|        at (#26:1)
```

----
# JDK12
----
# JDK12 JEPs so far
2 JEPs related to writing codes

- 326: Raw String Literals (Preview)
- 325: Switch Expressions (Preview)

----
# 326: Raw String Literals (Preview)
Raw String Literals(RSL) make it easier to write a string literal with `\n`, `\` and `"`
It can span multiple lines of code

```
var str = `
  <head>
  <title>Hello</title>
  <meta name="robot" content="all">
  </head>
  `
```

----
# Preview features is disabled by default
`--enable-preview` switch is required

```
jshell> `foo`
|  Error:
|  raw string literals are a preview feature and are disabled by default.
|    (use --enable-preview to enable raw string literals)
|  `foo`
|  ^
```

----
# Preview features is disabled by default
`--enable-preview` switch is required

```
oco2018 $ jshell --enable-preview
|  Welcome to JShell -- Version 12-ea
|  For an introduction type: /help intro

jshell> `test`
$1 ==> "test"
```

----
# Including ` in a raw string
Use `` to include ` in a raw string

```
jshell> ``select `name` from users``
$57 ==> "select `name` from users"
```
----
# Support method for RSL
RSL will be include indentational spaces

```
jshell> var s = `
   ...>         test
   ...>         `
s ==> "\n        test\n        "
```
----
# Support method for RSL
Two method is introduced to address an indentation in RSL

- align(int)
- indent(int)

----
# align(int)
Remove horizontal and vertical margin with remaining a specified indentation

```
jshell> var s = `
   ...>         test
   ...>         test
   ...>         `
s ==> "\n        test\n        test\n        "

jshell> s.align()
$7 ==> "test\ntest\n"
```

The first blank line is removed

----
# indent(int)
Adding a specified number of indentation spaces

```
jshell> `
   ...> test
   ...>   test
   ...> `.indent(2)
$3 ==> "\n  test\n    test\n"
```

----
# Raw string literal will be dropped from JDK12
😰😰😰

`` seems a blank string.
Quote character is rare. We can't use the backquote profligately.

----
# 325: Switch Expressions (Preview)
Extend switch statement

- `case` can take multiple values
- use `->` for a single line
- can be used as an expression (not implemented yet)

```
var s = switch (a) {
  case 1, 2 -> "One or Two";
  case 3 -> "Three";
};
```
----
# Thank you