JShell is Java’s first official REPL (READ-EVAL-PRINT-LOOP) tool. It is part of JDK 9 which is released recently by Oracle.
JShell REPL creates a simple programming environment in the command line that reads user’s input, evaluates it, prints the result, and then repeats the same cycle.
It works similar to Python interpreter or other JVM languages that have a REPL like Scala, Kotlin and Groovy.
You can write Java language expressions and statements in the JShell REPL, and they will be evaluated on their own without having to wrap them in classes or methods.
In this article, You’ll first setup JShell in your machine and then learn to play around with it using simple examples.
Hello JShell
JShell comes bundled with JDK 9. You can download JDK 9 from Oracle’s Java SE Downloads Page. Before proceeding further, download JDK 9 for your operating system and set it up in your PATH
variable.
Once JDK 9 is installed, type jshell
in your terminal to start a JShell session -
$ jshell
| Welcome to JShell -- Version 9
| For an introduction type: /help intro
jshell>
An interactive JShell session will be started and JShell will greet you with a welcome message.
If this doesn’t work, Please make sure that JAVA_HOME
is set in your machine and JAVA_HOME/bin
is added to the PATH
variable. All the JDK tools including Jshell
are located inside JAVA_HOME/bin
directory.
If it worked, then let’s write our first Hello, World
example using JShell -
jshell> System.out.println("Hello, World!")
Hello, World!
Yeah! That’s all you need to do! No need to define a class, create a main method and print hello world inside the main method. Just type the print statement, press enter and walla, you get the result instantly!
Also, You might have noticed that I didn’t terminate the statement with a Semicolon. Yes, Semicolons are Optional for bare expressions and statements. However, they’re required when you write multi-line statements or methods.
Variables and Expressions
You can type any valid Java expression in the REPL, be it arithmetic operation, string manipulation, method call, whatever, and it will be evaluated immediately.
jshell> 2+2
$1 ==> 4
jshell> 12*8
$2 ==> 96
As you might have noticed, all the results are automatically assigned to a variable created by the REPL. These variables are prefixed with $
. You can refer them in the REPL like this -
jshell> $1 + $2
$3 ==> 100
You can also create your own variables and refer them like this -
jshell> int width = 40
width ==> 40
jshell> int height = 30
height ==> 30
jshell> int area = width * height
area ==> 1200
Following are some examples of String manipulation in the REPL -
jshell> "Hello, " + "World"
$7 ==> "Hello, World"
jshell> String greeting = "Hello, World"
greeting ==> "Hello, World"
jshell> greeting.toUpperCase()
$9 ==> "HELLO, WORLD"
jshell> greeting.substring(0, 5)
$10 ==> "Hello"
jshell> greeting.split(",")
$11 ==> String[2] { "Hello", " World" }
Control Flow Statements (If-Else, While-Loops, For-Loops)
You can also write multi-line control flow statements in the REPL. JShell is smart enough to recognize multi-line statements and prompts with a ...>
symbol to let you enter the next line of the statement.
Following is an example of If-Else statement -
jshell> int age = 25
age ==> 25
jshell> if(age < 25) {
...> System.out.println("Child!");
...> } else {
...> System.out.println("Adult!");
...> }
Adult!
And, Here is how you can use a while loop in the REPL -
jshell> int i = 0
i ==> 0
jshell> while(i < 10) {
...> System.out.print(i + " ");
...> i++;
...> }
0 1 2 3 4 5 6 7 8 9
Finally, following is an example of a For-Loop -
jshell> String[] animals = {"Cat", "Dog", "Lion", "Tiger"}
animals ==> String[4] { "Cat", "Dog", "Lion", "Tiger" }
jshell> for(String animal : animals) {
...> System.out.println(animal);
...> }
Cat
Dog
Lion
Tiger
Defining and Invoking Methods
You can define methods in the REPL similar to how you define them in Java classes -
jshell> int sum(int a, int b) {
...> return a + b;
...> }
| created method sum(int,int)
Once a method is created in a JShell session, you can call it anytime until you quit that session -
jshell> sum(4, 5)
$12 ==> 9
Creating Classes and Objects
You’re not just limited to simple statements and functions. You can also create classes, interfaces and enums in JShell -
jshell> class Circle {
...> private double radius;
...> Circle(double radius) {
...> this.radius = radius;
...> }
...> double getRadius() {
...> return radius;
...> }
...> void setRadius(double radius) {
...> this.radius = radius;
...> }
...> double calculateArea() {
...> return 2 * Math.PI * radius;
...> }
...> }
| created class Circle
jshell> Circle c = new Circle(5.0)
c ==> Circle@1ce92674
jshell> c.calculateArea()
$3 ==> 31.41592653589793
Exploring JShell Commands
Apart from running Java language expressions and statements, JShell also provides some meta-commands to help you play around with the REPL environment.
You can use these commands to list the variables, methods, and imports available in the current JShell session, view the history of what you have typed, edit an already defined variable or method, save your workspace and open any existing workspace.
Type /help
or /?
to get a list of all the available commands. Let’s look at some of these commands -
1. /imports - List all available imports
JShell imports some of the most used and important Java packages by default when you start a session. Type /imports
command to get a list of all these imports -
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.*
You can import additional packages in JShell session like this -
jshell> import java.time.*
Once you do this, /imports
command will start showing the new import as well.
2. /vars - List all the variables defined in the current JShell session
/vars
command lists all the variables that are declared in the current JShell session along with their value -
jshell> /vars
| int $1 = 4
| int $2 = 96
| int $3 = 100
| int width = 40
| int height = 30
| int area = 1200
| String $7 = "Hello, World"
| String greeting = "Hello, World"
| String $9 = "HELLO, WORLD"
| String $10 = "Hello"
| String[] $11 = String[2] { "Hello", " World" }
| int age = 25
| int i = 10
| String[] animals = String[4] { "Cat", "Dog", "Lion", "Tiger" }
| int $17 = 9
3. /methods - List all the methods defined in the current JShell session
jshell> /methods
| int sum(int,int)
4. /types - List all the classes, interfaces and enums defined in the current JShell session
jshell> /types
| class Circle
5. /edit - Edit an already defined method, variable or class
You can edit an already defined method or variable using /edit
command. In the following example, I’m editing the sum()
method that we defined earlier.
jshell> /edit sum
The /edit
command opens an editor where you can edit the method and then save it. When you exit the editor, JShell will tell you that the method is modified -
| modified method sum(int,int)
6. /set - Set JShell configuration info
The /set
command allows you to configure JShell environment.
If you used the /edit
command in the previous section, then you might have noticed that JShell opens the source in its default editor. If let’s say, you want to use Vim instead of the default editor, you can set it using the following command -
jshell> /set editor vim
| Editor set to: vim
7. /save - Save the current workspace to a file
You can save all the source that you have typed in the current JShell session in a file using /save
command -
jshell> /save experiments.txt
8. /open - Open an already saved workspace
The /open
command allows you to open a file as source input for the current JShell session -
jshell> /open experiments.txt
Apart from loading snippets and commands from external files, you can also use /open
command to load a class in the JShell session from an external file.
Assuming you have defined a class named Square
in the current working directory, Here is how you can load the class in JShell -
jshell> /open Square.java
If you check the output of /types
command, the new class will be listed in the output -
jshell> /types
| class Circle
| class Square
Other Useful Features
1. Tab Completion
You get tab completion out of the box with JShell. You can type part of the source and press tab for suggestions. Consider the following example -
jshell> URL blogUrl = new URL("https://www.callicoder.com")
blogUrl ==> https://www.callicoder.com
Now, for checking what methods are available for use for the above URL object, type blogUrl
followed by a dot (.)
, and then press tab
-
jshell> blogUrl.
equals( getAuthority() getClass() getContent( getDefaultPort() getFile() getHost() getPath()
getPort() getProtocol() getQuery() getRef() getUserInfo() hashCode() notify() notifyAll()
openConnection( openStream() sameFile( toExternalForm() toString() toURI() wait(
jshell> blogUrl.
JShell will display all the methods that you can use on the blogUrl
object. This is awesome! isn’t it? :)
2. Forward References
JShell supports forward references. That means you can define functions that refer to other methods or variables that will be defined later -
jshell> int geometricSequence(int a, int r, int n) {
...> return a * pow(r, n-1);
...> }
| created method geometricSequence(int,int,int), however, it cannot be invoked until method pow(int,int) is declared
3. Redeclaring Variables and Methods
You can re-declare variables and methods without worrying about any previous declarations.
In the following example, the variable foo
is simply re-declared every time -
jshell> int foo = 123
foo ==> 123
jshell> int foo = 567
foo ==> 567
jshell> String foo = "Hello"
foo ==> "Hello"
Similarly, you can change the definition of methods as well -
jshell> int multiply(int a, int b) {
...> return a * b;
...> }
| created method multiply(int,int)
jshell> int multiply(int a, int b) {
...> // Multiplying two numbers
...> return a * b;
...> }
| modified method multiply(int,int)
JShell will simply say that It has modified an already existing method with the same name.
4. No checked Exceptions
Checked exceptions are automatically wrapped by JShell in the background. So you don’t have to catch them explicitly -
jshell> Thread.sleep(1000)
However, If you’re writing an entire method instead of a single statement, then you’ll need to handle checked exceptions -
jshell> Thread myThread = new Thread(() -> {
...> Thread.sleep(1000);
...> });
| Error:
| unreported exception java.lang.InterruptedException; must be caught or declared to be thrown
| Thread.sleep(1000);
| ^----------------^
Additional Examples
Collections
jshell> List<String> animals = List.of("Cat", "Dog", "Elephant", "Lion", "Tiger")
animals ==> [Cat, Dog, Elephant, Lion, Tiger]
jshell> animals.forEach(animal -> System.out.print(animal + " "))
Cat Dog Elephant Lion Tiger
jshell> Map<String, Integer> myMap = Map.of("one", 1, "two", 2, "three", 3)
myMap ==> {two=2, three=3, one=1}
jshell> Set<Integer> mySet = Set.of(1, 2, 4, 8, 16, 32)
mySet ==> [32, 4, 8, 2, 1, 16]
Streams
jshell> Stream<Integer> myStream = Stream.of(1, 2, 3, 4, 5)
myStream ==> java.util.stream.ReferencePipeline$Head@e720b71
jshell> myStream.map(number -> number * number).
...> filter(number -> number % 2 == 0).
...> forEach(System.out::println)
4
16
DateTime
jshell> import java.time.*;
jshell> LocalDateTime.now()
$30 ==> 2017-08-29T09:15:15.603432
Conclusion
JShell is definitely one of the coolest features of Java 9. It will help beginners get a grasp of the language quickly. Moreover, It will help other developers run quick experiments without writing classes, methods, imports and all that boilerplate.
I urge you to try out JShell and let me know your views about it in the comment section below.
Thank you for reading folks. See you in the next post. Happy Coding!