Getting Started with JShell Part 3
Learn the basics of JShell, a Read-Evaluate-Print-Loop command line tool, including executing simple statements, defining classes, and commands to manage code snippets.
Dec 14, 2018 • 11 Minute Read
Preface
In the previous guide in this series, you learned the basics of JShell.
In this guide, you'll learn how to manage code snippets and use JShell to explore libraries.
Managing Code Snippets
JShell has a few more commands on its own. You can see the complete list by typing /help or /?:
jshell> /help
| Type a Java language expression, statement, or declaration.
| Or type one of the following commands:
| /list [<name or id>|-all|-start]
| list the source you have typed
| ...
The most useful commands are probably the ones that help you manage code snippets.
The first one is list, which lists by default, all the valid statements you have typed since starting the session:
jshell> /list
1 : "Hello World"
2 : $1
3 : System.out.println($1)
There's another command that does something similar: /history. The difference is that /history presents all the statements (valid or not) and commands that you have typed:
jshell> /history
/help
"Hello World"
$1
System.out.println($1)
Sys
/list
/history
You can also list only variables with /var, only methods with /methods, or only types with /types:
jshell> /vars
| String $1 = "Hello World"
However, the advantage of /list is that it shows you a numeric identifier for each snippet that you can use to rerun it with /<id>:
jshell> /3
System.out.println($1)
Hello World
Delete it with the /drop command:
jshell> /drop 2
jshell> /list
1 : "Hello World"
3 : System.out.println($1)
Or edit it:
jshell> /edit 1
In this case, a window will open with a simple editor that will help you modify the snippet:
This editor comes in handy to add or modify multi-line statements like classes or methods and it won't be closed until you click on the Exit (saving the changes) or Cancel (discarding the changes) buttons.
However, in the case of implicit variables, notice that instead of modifying the variable, JShell creates another variable with the new value:
jshell> /edit 1
$4 ==> "Hello World modified"
jshell> /list
1 : "Hello World"
3 : System.out.println($1)
4 : "Hello World modified";
jshell>
This doesn't happen with explicitly named variables or types.
You can also use the name of the variable or type with these commands. For example, using the Book class defined in the previous section:
jshell> class Book {
...> private String title;
...> public void setTitle(String title) { this.title = title; }
...> public String getTitle() { return title; }
...> }
| created class Book
jshell> /list
1 : "Hello World"
3 : System.out.println($1)
4 : "Hello World modified";
5 : class Book {
private String title;
public void setTitle(String title) { this.title = title; }
public String getTitle() { return title; }
}
jshell>
We can edit it with the command:
jshell> /edit Book
If we modify the class in this way:
class Book {
private String title = "<NO TITLE>";
public void setTitle(String title) { this.title = title; }
public String getTitle() { return title; }
public String toString() { return "Book: " + title; }
}
And click on Exit, JShell will update the definition of the class (notice that the ID also changed):
jshell> /edit Book
| replaced class Book
jshell> /list
1 : "Hello World"
3 : System.out.println($1)
4 : "Hello World modified";
6 : class Book {
private String title = "<NO TITLE>";
public void setTitle(String title) { this.title = title; }
public String getTitle() { return title; }
public String toString() { return "Book: " + title; }
}
If you execute the /edit command without an argument, the editor will let you modify all the current statements in the session (and even add some if you want):
Using JShell to Explore Libraries
jshell> /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 other packages, but how does JShell know where to look for custom packages?
Consider the following case:
jshell> import com.mycompany.*
What you have to do is add the packages to the JShell classpath with the /env -class-path <path> command (if we already started a JShell session) or the option $jshell --class-path <path> (on the command-line).
You can specify a directory (in this example, it's the current directory):
jshell> /env -class-path .
Or a list of directories, JARs, or ZIP archives to search for compiled class files (the list must be separated with : on Linux/Mac and ; on Windows). You can find out more by executing /help context.
This way, assuming you have downloaded the Guava JAR in C:\, we can execute the following command:
jshell> /env -class-path C:\guava-23.0.jar
| Setting new options and restoring state.
As you can see from the message, it will restore the session with the new classpath setting, which means that it will run all valid snippets executed until that point.
If the library you want to test depends on other libraries, you have to download those dependencies and add them to the classpath too.
Now, you can import the classes from Guava's packages. Start typing:
jshell> import com.google.common.primitives.
And then press Tab so JShell can present some options:
jshell> import com.google.common.primitives.
Booleans Bytes Chars Doubles Floats
ImmutableDoubleArray ImmutableIntArray ImmutableLongArray Ints Longs
Primitives Shorts SignedBytes UnsignedBytes UnsignedInteger
UnsignedInts UnsignedLong UnsignedLongs
This is where JShell auto-completion comes in handy.
JShell's auto-completion capabilities allow you to view:
- Classes in a package
- Class members
- The parameters required by a method
- The list of overloads for a method
- Documentation of classes and their members
Let's import the Longs class:
jshell> import com.google.common.base.Longs
If we type Longs. and press Tab, JShell will show the class’s static members:
jshell> Longs.
BYTES MAX_POWER_OF_TWO asList(
class compare( concat(
constrainToRange( contains( ensureCapacity(
fromByteArray( fromBytes( hashCode(
indexOf( join( lastIndexOf(
lexicographicalComparator() max( min(
stringConverter() toArray( toByteArray(
tryParse(
The names that are not followed by parentheses (like BYTES) are static variables. All the other names are static methods:
- If the method name is followed by () (like lexicographicalComparator()), it means that the method doesn't require any arguments.
- If the method name is followed by an opening parenthesis, (, it means that the method requires at least one argument or that it is overloaded.
If you want to know more about the method indexOf type the name of this method and its opening parenthesis (the name can be auto-completed too), and press Tab:
jshell> Longs.indexOf(
Signatures:
int Longs.indexOf(long[] array, long target)
int Longs.indexOf(long[] array, long[] target)
<press tab again to see documentation>
If you press Tab again, you'll see the Javadoc of the first overload:
jshell> Longs.indexOf(
int Longs.indexOf(long[] array, long target)
<no documentation found>
<press tab to see next documentation>
In this case , there is no documentation is found. But you can keep pressing Tab to see the documentation of the next methods:
jshell> Longs.indexOf(
int Longs.indexOf(long[] array, long[] target)
<no documentation found>
<press tab again to see all possible completions; total possible completions: 600>
You can do this kind of exploration with any class, even at class level:
jshell> String
String StringBuffer StringBufferInputStream
StringBuilder StringIndexOutOfBoundsException StringJoiner
StringReader StringTokenizer StringWriter
Strings
Signatures:
java.lang.String
<press tab again to see documentation>
jshell> String
java.lang.String
The String class represents character strings. All string literals in Java programs, such as
"abc", are implemented as instances of this class.
...
Unless otherwise noted, passing a null argument to a constructor or method in this class will
<press tab again to see next page>
Or with any object to show its instance members:
jshell> "Hello".
charAt( chars() codePointAt( codePointBefore( codePointCount(
...
Conclusion
JShell is an important addition to the Java language. Users can easily and quickly verify things like return types, adjust formatting options, or try out libraries or language features.
Hopefully this guide taught you what you needed to know about how to work with various types of code snippets in JShell, some of its useful commands, and its auto-completion capabilities to explore a class’ members and documentation.
Of course, this guide only scratches the surface. Advanced users should look forward to learning more about feedback modes, custom options (like setting a custom editor), and ways of integrating JShell into your Java programs. A good resource to learn about some of these topics is Robert Field's tutorial on JShell.