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 ==> 96As 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 ==> 100You 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 ==> 1200Following 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 9Finally, 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
TigerDefining 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 ==> 9Creating 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 Circlejshell> Circle c = new Circle(5.0)
c ==> Circle@1ce92674
jshell> c.calculateArea()
$3 ==> 31.41592653589793Exploring 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 = 93. /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 Circle5. /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 sumThe /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: vim7. /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.txt8. /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.txtApart 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.javaIf you check the output of /types command, the new class will be listed in the output -
jshell> /types
| class Circle
| class SquareOther 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.comNow, 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 declared3. 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
16DateTime
jshell> import java.time.*;
jshell> LocalDateTime.now()
$30 ==> 2017-08-29T09:15:15.603432Conclusion
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!