JShell is a new interactive command line tool for accessing the Java language. It is introduced in Java 9. Working with JShell is similar to using the python interpreter via commandline. These tools can be collectively called as REPL (Read-Eval-Print-Loop) because they take inputs, evaluate and returns output to the user via command line. You can also use JShell as an API within other applications and code to the API to implement further enhancements in the application.
Installation
JShell comes with jdk 9 which will have a General Access release in July 2017. As of now, the early access meant for testing the application is available at : http://jdk.java.net/9. Once installed, change JAVA_HOME to the Java 9’s JDK installation folder. If path is set correctly, java -version should point to jdk 9-ea.
Running JShell
JShell can be accessed via command prompt. Currently, to allow printf() to be used with ease, you need to invoke jshell via command prompt in following manner:
1 2 3 4 |
C:\Users\Matrix>jshell --start DEFAULT --start PRINTING | Welcome to JShell -- Version 9-ea | For an introduction type: /help intro jshell> |
The command above imports all the built-in printing methods. Simple print statement can be thus invoked as:
1 2 |
jshell> print("Welcome to JShell Tutorial"); Welcome to JShell Tutorial |
JShell Commands
JShell provides a list of commands that could be used for snippet manipulation. We will cover important commands one by one.
/help
Gives access to help menu. Further help on a particular command can be accessed by typing:
1 |
/help commandname |
/list
Lists all the snippets that we have typed into the particular jshell session.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
jshell> String s = "abc"; s ==> "abc" jshell> String t = "def"; t ==> "def" jshell> StringBuilder sb = new StringBuilder(); sb ==> jshell> sb.append(s).append(t); $4 ==> abcdef jshell> sb.reverse(); $5 ==> fedcba jshell> /list 1 : String s = "abc"; 2 : String t = "def"; 3 : StringBuilder sb = new StringBuilder(); 4 : sb.append(s).append(t); 5 : sb.reverse(); jshell> |
/history
Gives history of commands that we typed in. While /list will list only the successfully run programming snippets alongwith the snippet number, /history lists everything that we entered into the console so far since the start of the jshell session:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
jshell> /list 1 : String s = "abc"; 2 : String t = "def"; 3 : StringBuilder sb = new StringBuilder(); 4 : sb.append(s).append(t); 5 : sb.reverse(); jshell> meh | Error: | cannot find symbol | symbol: variable meh | meh | ^-^ jshell> /history String s = "abc"; String t = "def"; StringBuilder sb = new StringBuilder(); sb.append(s).append(t); sb.reverse(); /list meh /history |
/exit
Used to exit the JShell session.
/save
While working on a prototype, often we would like to save current work and close jshell session so that we can resume work from that point after opening the session again. For this backup process /save command is used.
/open
Once the backup is added, we may want to restore the saved session. This is done using open command.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
jshell> /save mylist.txt jshell> /exit | Goodbye C:\Users\Matrix>jshell --start DEFAULT --start PRINTING | Welcome to JShell -- Version 9-ea | For an introduction type: /help intro jshell> /list jshell> /open mylist.txt jshell> /list 1 : String s = "abc"; 2 : String t = "def"; 3 : StringBuilder sb = new StringBuilder(); 4 : sb.append(s).append(t); 5 : sb.reverse(); jshell> |
/!
Reruns the last snippet
/<id>
Rerun the snippet with the mentioned snippetid.
/-<n>
Rerun the nth snippet from the last
/imports
Lists down all imports that are available.
1 2 3 4 5 6 7 8 9 10 11 |
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.* |
/vars
Lists all the variables declared with their values.
1 2 3 4 5 6 |
jshell> /vars | String s = "abc" | String t = "def" | StringBuilder sb = fedcba | StringBuilder $4 = fedcba | StringBuilder $5 = fedcba |
/methods
Lists all the declared as well as imported methods.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
jshell> boolean isEven(int n){ return (n%2==0);} | created method isEven(int) jshell> /methods | void print(boolean) | void print(char) | void print(int) | void print(long) | void print(float) | void print(double) | void print(char s[]) | void print(String) | void print(Object) | void println() | void println(boolean) | void println(char) | void println(int) | void println(long) | void println(float) | void println(double) | void println(char s[]) | void println(String) | void println(Object) | void printf(java.util.Locale,String,Object...) | void printf(String,Object...) | boolean isEven(int) |
Here, all the print statements were automatically imported as we gave –start PRINTING as a command line parameter to jshell during invocation. Notice that the new function created is added to end of the list.
/edit
Used to edit a particular snippet already added to the list in JShell.
In the above case, a new function is created as the method name itself is changed. We will change the variable name from n to x. Notice the changes in definition of isOdd before and after modification.
/drop
Drop a snippet by its id from the list.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
jshell> /list 1 : String s = "abc"; 2 : String t = "def"; 3 : StringBuilder sb = new StringBuilder(); 4 : sb.append(s).append(t); 5 : sb.reverse(); 6 : boolean isEven(int n){ return (n%2==0);} 8 : isOdd(5); 9 : isEven(5); 10 : boolean isOdd(int x){ return (x%2!=0);} jshell> /drop 9 | dropped variable $9 jshell> /list 1 : String s = "abc"; 2 : String t = "def"; 3 : StringBuilder sb = new StringBuilder(); 4 : sb.append(s).append(t); 5 : sb.reverse(); 6 : boolean isEven(int n){ return (n%2==0);} 8 : isOdd(5); 10 : boolean isOdd(int x){ return (x%2!=0);} jshell> |
Thus, we have covered most of the major built-in commands of JShell.
Running A Whole Java File As A Snippet
Consider a simple Java class with a main function.
1 2 3 4 5 6 7 8 9 10 |
class TestSnippet{ public static void main(String[] args){ System.out.println("Hello World!"); } public int getTicketNumber(){ return (int) (31 * Math.random()); } } |
This can be added as a java snippet and executed in jshell:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
jshell> /open G:\learnings\TestSnippet.java jshell> /list 1 : String s = "abc"; 2 : String t = "def"; 3 : StringBuilder sb = new StringBuilder(); 4 : sb.append(s).append(t); 5 : sb.reverse(); 6 : boolean isEven(int n){ return (n%2==0);} 8 : isOdd(5); 10 : boolean isOdd(int x){ return (x%2!=0);} 12 : class TestSnippet{ public static void main(String[] args){ System.out.println("Hello World!"); } public int getTicketNumber(){ return (int) (31 * Math.random()); } } jshell> TestSnippet.main(new String[0]); Hello World! jshell> new TestSnippet().getTicketNumber(); $14 ==> 7 jshell> new TestSnippet().getTicketNumber(); $15 ==> 28 jshell> /15 new TestSnippet().getTicketNumber(); $16 ==> 17 |
Note that TestSnippet.main() always executes the main method. /15 in last jshell session reruns the method getTicketNumber().
Integrating JShell With Other Applications
It is possible to create a new JShell instance programmatically using Java. The JShell and its associated APIs can be found under the package jdk.jshell. There is a proposal to incorporate this in various IDEs like Eclipse and NetBeans. This is some work that is in progress and may be completed only after GA release of Java 9.
Let us learn how to program with JShell API with a small example:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
import java.util.List; import jdk.jshell.*; public class JShellTest { public static void main(String[] args) { JShell js = JShell.create(); List<SnippetEvent> snippetsList = js.eval("int c = 4+5*6;"); System.out.println("Size of snippetEventList : " + snippetsList.size()); System.out.println("Value of the expression is : " + snippetsList.get(0).value()); } } |
In the above program, we get a new instance of state engine for Jshell programmatically using the static function create().
Jshell.eval() is used to add an expression to the Jshell instance. The eval() method returns a list of events that are triggered by the evaluation. The evaluation should be exactly one snippet which can be an expression, a statement, method, class or variable declaration or an import statement. For a method, class or variable declaration that is added as an input for this eval statement, modifiers like public, protected, private, static and final are not allowed. If there was a previous definition with same signature, then that will be overwritten with the current one. The Status of SnippetEvent will be changed to OVERWRITTEN.
Each SnippetEvent created from the eval method can be checked for the output of the expression using SnippetEvent.value().
Output of the above program:
1 2 |
Size of snippetEventList : 1 Value of the expression is : 34 |
Summary
Jshell is an exciting addition to the Java. And should help Java to be accepted in the educational institutions. Learning of programming languages usually starts with languages that are easy to execute and don’t need any boilerplate coding to execute a simple print statement. Jshell brings the REPL to Java and this should help the language in future.
I like your blog.