Interactive Java with jshell

So far we used Nashorn to emulate a Read-Eval-Print-Loop (REPL) for Java. But Java 9 can do better. This version includes a real REPL – the command line tool jshell. Although the Early Access (EA) version is not intended for production, you still can use it for interactively working with Java.

Download the latest JDK-9 [1]. Either choose your version from JDK 9 snapshot releases or JDK 9 Early Access with Project Jigsaw. The latter one includes the upcoming module system (at the time of this writing – it will be included into the normal setup someday…).

Open a terminal or command prompt to start jshell.

d:\bin\jdk-9\bin\jshell.exe

Replace the path with the one you use. In my previous blogs I described how to run a command line tool within NetBeans’ terminal window. Sadly on two different Windows systems, the output of jshell had been invisible within the terminal window. I’m sure, the NetBeans team will find a solution soon. Using a Linux operating system (I used Ubuntu), there is no such problem.

Let’s perform the same task as we did before with Nashorn. I promise it will be much simpler using jshell! If you need to download the sample code, please take a look into my former blog [2].

First we need to add ParallelStreams.jar to the classpath. There is no need to define any classpath before invoking jshell. You can add a classpath at any time.

-> /classpath ./ParallelStreams.jar

“->” is jshell’s command prompt. The leading / indicates a jshell command. Get a list of all commands by /help. Other input is treated as Java instructions.

As we usually do in our Java source, we can perform an import of the classes we want to reference.

-> import de.muellerbruehl.parallelstreams.*

This import differs slightly to Java source: There is no semicolon at the end of the line. Of course, you can use a semicolon. But it can be omitted, if you prefer.

Next, load the person manager (that’s what the class Persons really is).

-> Persons pm = Persons.getInstance()

As before, this takes some time, because this generates the demo data. Sadly this takes a bit longer than it does when running the jar with Java. Once loaded, we can start querying the data.

-> pm.getPersons().size()

There is no need to print the result, cause jshell alerts this automatically:

|  Expression value is: 50000
|    assigned to temporary variable $3 of type int

And, this value is assigned to a temporary variable. You may use this variable later on if you like.

At the time of this writing, the current build of JDK 9 EA is 107. If you try to assign the persons to a list, jshell crashes. Hopefully we can do it like this in a later version:

List<Person> persons = pm.getPersons()

Next, let’s check the stream

-> pm.getPersons().stream().count()

Because it is Java, we can use lambda expressions using the normal syntax. No special translation (as we used for Nashorn) is needed.

pm.getPersons().stream().filter(p -> p.getAge() < 20).count()

And it is possible to split a more complex query

-> pm.getPersons().parallelStream()
|  Expression value is: java.util.stream.ReferencePipeline$Head@78ac1102
|    assigned to temporary variable $6 of type java.util.stream.Stream<Person>

-> $6.filter(p -> p.isVendor())
|  Expression value is: java.util.stream.ReferencePipeline$2@a74868d
|    assigned to temporary variable $7 of type java.util.stream.Stream<Person>

-> $7.flatMapToLong(p -> p.getSelling().values().stream().mapToLong(
a -> a.getQuantity())).sum()
|  Expression value is: 2137950
|    assigned to temporary variable $8 of type long

In the example above, jshell could create intermediate results, which had been assigned to temporary variables. If we slightly change the input in a manner that the statement needs to continue, then jshell changes the prompt to indicate the continuation of the input (>>).

-> pm.getPersons().parallelStream().
>> filter(p -> p.isVendor()).
>> flatMapToLong(p -> p.getSelling().values().
>> stream().mapToLong(a -> a.getQuantity())).sum()
|  Expression value is: 2137950

jshell comes along with tab completion. You may edit your session and apply it again (/edit). Or save (/save) your commands and reload it (/open) within another session. Start playing around with the commands and explore Java statements or libraries.

Conclusion

Java 9 offers a real REPL. jshell is a an exciting tool to explore Java libraries interactively. It can be used for training purpose too, e.g. testing different kind of lambda and stream expressions.

Have fun!

 

[1] jdk9.java.net

[2] blog.mueller-bruehl.de/netbeans/interactive-java-using-nashorn-part-ii

Leave a Reply

Your email address will not be published. Required fields are marked *