Jshell: exploring Java 9 REPL
Remember the days when you need to write at least one class to test a small snippet of Java code ?! well, those days will be soon from the past once java 9 is released. JShell is the first official Java REPL (Read-Eval-Print-Loop), a command line tool that lets you run Java statements on their own without having to wrap them in classes or methods. Similar in a way to Python’s interpreter, or to other JVM languages that natively support REPL like Scala and Groovy.
Run it
Of course, you need to install java 9 on you machine to get started with jshell. If you've a mac, this can be done easily using Homebrew:
$ brew cask install java9-beta
Also, I'm using jenv to switch easily between java versions. To play with Jshell, all what I need is to configure java 9 as a shell instance version, which is done by running:
$ jenv shell oracle64-9-ea
Now, after you've all set up, let's run REPL:
jshell
| Welcome to JShell -- Version 9-ea
| For an introduction type: /help intro
jshell>
If more detailed messaging from the shell is desired, a -v flag can be used:
jshell -v
As you've noticed, once it is ready, we will be greeted by a friendly message and a familiar Unix-style prompt at the bottom.
Default imports
To know about What are all the default imports available, we need to use “/imports” command as shown below:
jshell> /imports
| import java.util.*
| import java.io.*
| import java.math.*
| import java.net.*
| import java.util.concurrent.*
| import java.util.prefs.*
| import java.util.regex.*
You can add your own any time, as simply as:
import java.nio.ByteBuffer
Expressions
Any valid Java expression is accepted and the result of the evaluation will be shown. If no explicit receiver of the result is provided, “scratch” variables will be created:
jshell> 3 * 3
$1 ==> 9
| created scratch variable $1 : int
jshell> String.format("%d of bottles of water", $1)
$2 ==> "9 of bottles of beer"
| created scratch variable $2 : String
The REPL is quite helpful here by informing us that it created a scratch variable named $1 which value is 9 and its type is int.
Multi-line expressions are also possible. Jshell is smart enough to know when an expression is incomplete and will prompt the user to continue on a new line:
jshell> int var =
...> 5
var ==> 5
| created variable var : int
ote how the prompt changed to an indented …> to signify the continuation of an expression.
Defining Methods:
You can also define methods and even replace them:
jshell> void salam() { System.out.println("Hello! Can you hear me!"); }
| created method salam()
jshell> salam()
Hello! Can you hear me!
jshell> void salam() { System.out.println("I was wondering if after all this years you'd like to meet!"); }
| modified method salam()
| update overwrote method salam()
jshell> salam()
I was wondering if after all this years you'd like to meet!
jshell>
Tab-Completion
JShell supports Tab key in very nice way to avoid typing lot of characters and save our time. For example, let's consider this 2 (long) variables:
jshell> int veryLongVarNameOne = 1
veryLongVarNameOne ==> 1
jshell> int veryLongVarNameAgain = 2
veryLongVarNameAgain ==> 2
Now, to use one of them, just type couple of characters and press “Tab” key from your keyboard, it will provide you available hints to select. If there are more hits, it displays all of them as shown below.
jshell> veryLongVarName
veryLongVarNameAgain veryLongVarNameOne
Commands
Jshell provides quite a few meta-commands that aren’t related to evaluating Java statements. They all start with a forward-slash == / == to be distinguished from normal operations (remember the /import
that we started with?!). For example, we can request a list of all available commands by issuing /help
or /?
.
Let’s take a look at some of them.
listing variables:
Working in a REPL is not nearly as easy as having a full-featured IDE at our fingertips: it is easy to forget what variables have which values, what methods have been defined and so on. To check the state of the shell we can use /var, /methods, /list or /history:
jshell> /vars
| int $1 = 9
| String $2 = "9 of bottles of beer"
| int var = 5
listing methods:
jshell> /methods
| printf (String,Object...)void
| salam ()void
listing sources
jshell> /list
1 : 3 * 3
2 : String.format("%d of bottles of beer", $1)
3 : int var =
5;
5 : salam()
6 : void salam() { System.out.println("I was wondering if after all this years you'd like to meet!"); }
7 : salam()
History of our previous commands:
jshell> /history
3 * 3
String.format("%d of bottles of beer", $1)
int var =
5
/import
void salam() { System.out.println("Hello! Can you hear me!"); }
salam()
void salam() { System.out.println("I was wondering if after all this years you'd like to meet!"); }
salam()
/vars
/methods
/list
/history
The difference between /list and /history is that the latter shows commands in addition to expressions.
Saving
To save the expression history the /save command can be used:
jshell> /save repl.java
This saves our expression history into repl.java in the same directory from which we ran the jshell command.
Editing sources in external editor
jshell> /edit salam
Opens external editor, and replaces salam
method.
Exiting
When we are done with the work, the /exit command can terminate the shell:
jshell> /exit
| Goodbye
Well, That's all for this article. We took a look at Java 9 REPL. Since Java has been around for over 20 years already, perhaps it arrived a little late. However, it should prove to be another valuable tool in our Java toolbox.