Sign in Get started
WRIT E FOR US CODING INT ERVIEW COURS E →
You have 2 free stories left this month. Sign up and get an extra one for free.
JShell, the Java REPL
Easy command-line prototyping and more
Ben Weidig Follow
Feb 19 · 7 min read
Photo by Ahmed Sobah on Unsplash
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.
Many languages contain a REPL, a Read-Evaluate-Print Loop, which
evaluates declarations, statements, and expressions as they are entered
and immediately shows the results. With Java 9, we finally got one too.
Examples
To better visualize the examples, I refrained from using Gists. Instead, I
use bold for all user input, the JShell output is not emphasized. 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:
jshell [options] [load-files]
Snippets
JShell evaluates everything you throw at it: expressions, statements,
imports, or definitions. These chunks of Java code are called “snippets”.
# Expressions
jshell> 2 + 3
$1 ==> 5
# Statements
jshell> var a = 2 + 3
a ==> 5
# Imports
jshell> import java.time.*
# Definitions
jshell> boolean greaterZero(int i) {
...> return i > 0;
...> }
| created method greaterZero(int)
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:
jshell> 2 + 3
$1 ==> 5
jshell> String.valueOf($1)
$2 ==> "5"
jshell> String nonScratch = "value"
nonScratch ==> "value"
jshell> /vars
| int $1 = 5
| String $2 = "5"
| String nonScratch = "value"
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:
jshell> /imports
| 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.*
We can import other packages and classes just like we would in “normal”
Java code:
jshell> import java.time.*
jshell> import static java.util.stream.Collectors.*
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:
# cursor position
# ▼
jshell> var now = LocalDate.now() <shift-tab i>
0: Do nothing
1: import: java.time.LocalDate
Choice: 1
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 that will convert an expression to
a variable creation statement:
jshell> 3 + 3 <shift-tab v>
# New cursor position
# ▼
jshell> int = 3 + 3
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.
jshell> System.out.print <tab>
print( printf( println(
jshell> System.out.print
If we found the correct method, we can see all available signatures by
pressing tab again after the parenthesis:
jshell> System.out.println(
Signatures:
void PrintStream.println()
void PrintStream.println(boolean x)
void PrintStream.println(char x)
void PrintStream.println(int x)
void PrintStream.println(long x)
void PrintStream.println(float x)
void PrintStream.println(double x)
void PrintStream.println(char[] x)
void PrintStream.println(String x)
void PrintStream.println(Object x)
<press tab again to see documentation>
jshell> System.out.println(
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”:
jshell> String concat(String a, String b) {
...> return a + b;
...> }
| created method concat(String,String)
jshell> class SimplePojo {
...> private String value;
...> String getValue() {
...> return this.value;
...> }
...> void setValue(String newValue) {
...> this.value = newValue;
...> }
...> }
| created class SimplePojo
jshell> var pojo = new SimplePojo()
pojo ==> SimplePojo@67424e82
jshell> pojo.setValue("a value")
jshell> pojo.getValue()
$7 ==> "a value"
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:
jshell> void forwardReference() {
...> System.out.println(notYetDeclared);
...> }
| created method forwardReference(), however, it cannot be invoked
until variable notYetDeclared is declared
jshell> forwardReference()
| attempted to call method forwardReference() which cannot be
invoked until variable notYetDeclared is declared
jshell> var notYet = "variable is declared"
notYetDeclared ==> "variable is declared"
jshell> forwardReference()
variable is declared
This allows us to set up our environment easier than to ensure
everything has to be in place before creating methods etc.
Control Flow
Java control flow statements are supported:
if - else
? : Ternary operator
for and while -loops
switch 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.
jshell> 2 + 4
$1 ==> 6
jshell> String test = "42"
test ==> "42"
jshell> /history
2 + 4
String test = "42"
/history
Using /list instead, we get a list of snippets, but not commands, and
their corresponding ID.
jshell> 2 + 4
$1 ==> 6
jshell> String test = "42"
test ==> "42"
jshell> /list
1 : 2 + 4
2 : String test = "42";
The ID can be used in other commands.
Searching
JShell supports backwards and forward searching:
ctrl-r - Backward
ctrl-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 | Description
--------------------|------------------------------------
/! | Rerun last snippet
/-<n> | Rerun the last <n>-th snippet
/<id> | Rerun specific snippet
|
/list | List source of session
/vars | List variables
/types | List types
/methods | List methods
/imports | List imports
|
/history | Plain text history
/drop <name or id> | Delete source entry
/edit | Open all source in editor
/edit <id> | Open specific source in editor
/open <file> | Open file as source input
/save <file> | Save snippets to <file>
|
/reload | Reset and replay each snippet
/reset | Reset JShell
/env | View or change the evaluation context
/set <key> <value> | Configure JShell
/exit | Quit JShell
Command Abbreviations
We don’t have to type out the full command, just enough to make it
unique:
jshell> /set feedback verbose
VS.
jshell> /se fe v
/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:
jshell --class-path [directory or JAR files]
Or we can set it during an active session:
jshell> /env --class-path [directory or JAR files]
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:
jshell --module-path [module path] --add-modules [module]
This can also be set in an active session:
jshell> /env --module-path [module-path] --add-modules [module]
. . .
Configuration
With the help of /set , we can configure JShell to our liking.
Basic Configuration
Config key /values | Description
--------------------|--------------------------------------
editor <command> | Specify editor for "/edit"
start <file> | Contents of file will become default
| snippets/commands at startup
feedback <mode> | Verbosity of feedback
<none> | Display editor, start and feedback
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 a 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:
jshell --startup [script]
To use more than one start-up script, we need to use the argument --
start instead:
jshell --start [script] --start [script]
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 same imports as DEFAULT , but also adds multiple print
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:
jshell [load-file]
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
Sign up for "Top Stories" from Level Up Coding
A monthly summary of the best stories shared in Level Up Coding
Create a free Medium account to get "Top Stories" in
Get this newsletter your inbox.
Java Programming Software Development Development Coding
139 claps
WRIT T EN BY
Ben Weidig Follow
Software developer, entrepeneur, blogger. Mostly Java,
sometimes Swift, Golang, Bash and all the other fun stu .
Level Up Coding Follow
Coding tutorials and news. The developer homepage
gitconnected.com
See responses (1)
More From Medium
Linux user tries My Top 20 VS Code Tricky Java Interview 5 T hings T hat Are Hard
Windows, in 2020 Extensions Questions To Grasp When You
Dominik Tarnowski in Level Up Neo Hao Jun in Level Up Manusha Chethiyawardhana in Start Programming
Coding Coding Level Up Coding Daan in Level Up Coding
5 Lessons I’ve Learned Handling Authorization 4 JavaScript Tricks You 3 Habits T hat Will Help
on How to Structure In Clean Architecture Should Know You Become a Top
Code with ASP.NET Core and Anupam Chugh in Level Up Developer
Daan in Level Up Coding MediatR Coding Manish Jain in Level Up Coding
Austin Davies in Level Up
Coding
Discover Medium Make Medium yours Become a member
Welcome to a place where words matter. On Medium, smart Follow all the topics you care about, and we’ll deliver the Get unlimited access to the best stories on Medium — and
voices and original ideas take center stage - with no ads in best stories for you to your homepage and inbox. Explore support writers while you’re at it. Just $5/month. Upgrade
sight. Watch
About Help Legal