JShell, the Java REPL
Many languages contain a REPL, a Read-Evaluate-Print Loop. It evaluates declarations, statements, and expressions as they are entered and immediately shows the results. With Java 9, we finally got one too.
Quickly running some code without starting a full-blown IDE, or creating a scratch project can be immensely helpful. It can be used for prototyping code, trying some new functionality, or running a small part of a bigger project.
Table of Contents
Lines starting with #
are added for explanation purposes and are not part of the JShell output.
Basic Usage
To start a new JShell session, just type jshell
in your favorite terminal / command line:
Snippets
JShell evaluates everything you throw at it: expressions, statements, imports, or definitions. These chunks of Java code are called “snippets”.
No semicolons are needed for single-line snippets. If we define a method or class, we still need semicolons for the contents of curly brackets.
Scratch Variables
Any value returned by a snippet is automatically saved into a “scratch variable”, named $<number>
. Now the result of the expression is available to use later on.
To list all variables of the active session, type /vars
, which will print all scratch and non-scratch variables:
Imports
By default, only a small subset of the JDK is imported automatically.
Typing /imports
lists all imported packages and classes of the current JShell session:
We can import other packages and classes just like we would in “normal” Java code:
Or we can instruct JShell to load a different set of packages on start-up by using a predefined load-file: jshell JAVASE
This will load ~170 different packages from the JDK, instead of just the bare minimum.
Context-based Auto-Imports
No one wants to type out all the imports needed for working with Java code. It’s a good thing JShell has you covered!
To import a type we can press shift-tab i
at the end of any type, and JShell tries to find the correct type based on the context:
Not always an import-candidate will be found. But most of the time, it will make using JShell easier.
Expressions to Variables
Another handy shortcut is shift-tab v
which will convert an expression to a variable creation statement:
The variable type will be inferred and inserted automatically, just give it a name, press enter
, and you converted your expression to a named variable.
The Power of Tab
The tab completion is really powerful and can be used to complete snippets and commands. Pressing tab
multiple times increases the amount of information provided.
If we found the correct method, we can see all available signatures by pressing tab
again after the parenthesis:
As indicated in the output, pressing tab
again (and again and again) will cycle through the documentation of every signature.
Methods & Classes
Methods and classes can be declared “as usual”:
Forward Referencing
Thanks to forward referencing, our methods and classes can use variables and other constructs that aren’t even declared yet. JShell warns us about it, though:
This allows us to set up our environment easier than ensuring everything has to be in place before creating methods etc.
Control Flow
Java control flow statements are supported:
if
-else
? :
Ternary operatorfor
andwhile
-loopsswitch
statements
History
There are multiple ways to work with previous snippets.
Listing
The command /history
will display all snippets and commands of the currently active session in plain text.
Using /list
instead, we get a list of snippets, but not commands, and their corresponding ID.
The ID can be used in other commands.
Searching
JShell supports backward and forward searching:
ctrl-r
- Backwardctrl-s
- Backward
Commands
We already learned about some available commands, like /vars
and /list
.
Many commands have different options. We can check them out by typing /?
or /help
for a short overview. For a detailed explanation of a command, use/? <command>
or /help <command>
.
List of Commands
Command Abbreviations
We don’t have to type out the full command, just enough to make it unique:
VS.
/s
wouldn’t be enough for /set
, thanks to /save
.
External Code
Java provides a lot of functionality, but being able to use any JAR file in JShell makes it a potent tool for prototyping.
Classpath
We can either specify the classpath on startup:
Or we can set it during an active session:
Beware, the session will be reset, and everything not in a start-up script will be gone.
Java 9 Modules
Module usage are similar to using classpaths:
This can also be set in an active session:
Configuration
With the help of /set
, we can configure JShell to our liking.
Basic Configuration
Like other commands, editor
has additional options, you can check them out with /help /set editor
.
Persistence
By default, all /set
commands are only set for the duration of the current session. To set a configuration option permanently, we need to add the argument -retain
at the end.
But be aware, not every retained option can be removed with -delete
like the editor option.
I’ve tried to find out where JShell saves its configuration, but couldn’t find it, even after checking out the source code.
Advanced Configuration
We can configure the output provided by JShell in quite detail. But this would make this article twice or thrice as long.
If you’re interested in configuring the output, you should check out the /set mode
and /set format
options.
JShell Feedback Mode Documentation (Oracle)
Working with Scripts
Start-up Scripts
As mentioned before, JShell loads a default start-up script to prepare the session with useful imports.
We can use our own script at startup to prepare it the way we like it:
To use more than one start-up script, we need to use the argument --start
instead:
Or we can use /set start -retain [scripts]
instead.
There are 3 built-in start-up scripts available:
DEFAULT
: Loads a minimum of imports, used if no load-file is specified.JAVASE
: Loads ~175 different JDK packages.PRINTING
: Loads the same imports asDEFAULT
, but also adds multipleprint
convenience methods.
Startup scripts are always run when the session resets:
- Initial start-up
/reset
/reload
/env
Loading Scripts
Loading a script into a session is also possible:
Or use /open [load-file]
in a session.
Unlike a start-up script, it won’t be reloaded when the session resets.
Resources
- JShell User Guide (Oracle)
- JShell Tutorial (OpenJDK)
- JEP 222 (OpenJDK)
- Java 9 — Exploring the REPL (Baeldung)
- JShell Console in IntelliJ IDEA