Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
OrganizationEventAdvent CalendarQiitadon (β)
Qiita JobsQiita ZineQiita Blog
Help us understand the problem. What are the problem?

More than 1 year has passed since last update.


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

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

by nowokay
1 / 94

About me

  • Naoki Kishida
  • LINE Fukuoka
  • Twitter: @kis


  • 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


  • 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

スクリーンショット 2018-10-21 9.27.21.png

Haven't installed JDK11+ yet?

Web JShell console
スクリーンショット 2018-10-21 8.44.59.png

Restriction of TryJShell

JFrame is not allowed since TryJShell is a headless
スクリーンショット 2018-10-21 8.45.33.png


  • Exit JShell
  • /exi /ex also are allowed

We can abbreviate a command while it is not ambiguous

jshell> /exit
|  Goodbye
~ $


  • Show information
  • To specify a command to show the detail
jshell> /he help
|                                   /help
|                                   =====
|  Display information about using the jshell tool.


JShell returns a result of an expression you have entered.

jshell> 23 * 12
$1 ==> 276

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


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"


Show declared variables

jshell> 23+4
$1 ==> 27

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

jshell> /vars
|    int $1 = 27
|    String a = "hello"


  • 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


[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


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]
String String.toUpperCase(Locale locale)
String String.toUpperCase()

<press tab again to see documentation>


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.*



  • 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
import javax.swing.*
var f = new JFrame("JShell")
f.setSize(400, 300)


There are 16 JEPs in JDK11
スクリーンショット 2018-10-20 9.39.39.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()
HttpResponse<String> res = client.send(

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)
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)
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

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

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


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

(@Nullable var s) -> s + "!!!"



  • String
  • I/O
  • Util

New in String

  • repeat(int)
  • isBlank()
  • strip() / stripLeading() / stripTrailing()
  • lines()
  • Character.toString(int)


Repeat a string

jshell> "foo".repeat(3)
$38 ==> "foofoofoo"


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"


Split a string to stream by \n

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


jshell> Character.toString(65)
|  Error:
|  incompatible types: possible lossy conversion from int to char
|  Character.toString(65)
|                     ^^
jshell> Character.toString(65)
$15 ==> "A"

New in I/O

  • Path.of
  • Files
  • null I/O


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


  • writeString
  • readString


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

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


Read a file content as string
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

jshell> Reader.nullReader().read()
$13 ==> -1
jshell> Writer.nullWriter().write("hello")

New in java.util

  • Collection.toArray(IntFunction)
  • Predicate.not(Predicate)
  • Optional.isEmpty()


Until JDK10, need to specify the array size or receive Object array

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" }


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


The new API resolve the problem

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


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" }


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 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

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


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 = `
  <meta name="robot" content="all">

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)


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


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

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Help us understand the problem. What are the problem?