Java 9 – Exploring the REPL

1. Introduction

This article is about jshell, an interactive REPL (Read-Evaluate-Print-Loop) console that is bundled with the JDK for the upcoming Java 9 release. For those not familiar with the concept, a REPL allows to interactively run arbitrary snippets of code and evaluate their results.

A REPL can be useful for things such as quickly checking the viability of an idea or figuring out e.g. a formatted string for String or SimpleDateFormat.

2. Running

To get started we need to run the REPL, which is done by invoking:

$JAVA_HOME/bin/jshell

If more detailed messaging from the shell is desired, a -v flag can be used:

$JAVA_HOME/bin/jshell -v

Once it is ready, we will be greeted by a friendly message and a familiar Unix-style prompt at the bottom.

3. Defining and Invoking Methods

Methods can be added by typing their signature and body:

jshell> void helloWorld() { System.out.println("Hello world");}
|  created method helloWorld()

Here we defined the ubiquitous “hello world” method. It can be invoked using normal Java syntax:

jshell> helloWorld()
Hello world

4. Variables

Variables can be defined with the normal Java declaration syntax:

jshell> int i = 0;
i ==> 0
|  created variable i : int

jshell> String company = "Baeldung"
company ==> "Baeldung"
|  created variable company : String

jshell> Date date = new Date()
date ==> Sun Feb 26 06:30:16 EST 2017
|  created variable date : Date

Note that semicolons are optional. Variables can also be declared without initialization:

jshell> File file
file ==> null
|  created variable file : File

5. 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> String.format("%d of bottles of beer", 100)
$6 ==> "100 of bottles of beer"
|  created scratch variable $6 : String

The REPL is quite helpful here by informing us that it created a scratch variable named $6 which value is “100 of bottles of beer on the wall” and its type is String.

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 i =
   ...> 5;
i ==> 5
|  modified variable i : int
|    update overwrote variable i : int

Note how the prompt changed to an indented …> to signify the continuation of an expression.

6. 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. For example, we can request a list of all available commands by issuing /help or /?.

Let’s take a look at some of them.

6.1. Imports

To list all the imports active in the current session we can use the /import command:

jshell> /import
|    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.*

As we can see, the shell starts with quite a few useful imports already added.

6.2. Lists

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> /var
| int i = 0
| String company = "Baeldung"
| Date date = Sun Feb 26 06:30:16 EST 2017
| File file = null
| String $6 = "100 of bottles of beer on the wall"

jshell> /methods
| void helloWorld()

jshell> /list

 1 : void helloWorld() { System.out.println("Hello world");}
 2 : int i = 0;
 3 : String company = "Baeldung";
 4 : Date date = new Date();
 5 : File file;
 6 : String.format("%d of bottles of beer on the wall", 100)

jshell> /history

void helloWorld() { System.out.println("Hello world");}
int i = 0;
String company = "Baeldung"
Date date = new Date()
File file
String.format("%d of bottles of beer on the wall", 100)
/var
/methods
/list
/history

The difference between /list and /history is that the latter shows commands in addition to expressions.

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

6.4. Loading

To load a previously saved file we can use the /open command:

jshell> /open repl.java

A loaded session can then be verified by issuing /var, /method or /list.

6.5. Exiting

When we are done with the work, the /exit command can terminate the shell:

jshell> /exit
|  Goodbye

Goodbye jshell.

7. Conclusion

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

Leave a Reply

Your email address will not be published.