About me
- Naoki Kishida
- LINE Fukuoka
- Twitter: @kis
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/
Haven't installed JDK11+ yet?
Web JShell console
https://tryjshell.org/
Restriction of TryJShell
JFrame is not allowed since TryJShell is a headless
/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
import javax.swing.*
var f = new JFrame("JShell")
f.setSize(400, 300)
f.setVisible(true)
JEPs
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
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
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
(@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)
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
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
jshell> Reader.nullReader().read()
$13 ==> -1
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
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
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
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
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";
};