Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to run a whole Java file added as a snippet in JShell?

I tried installing JDK 9 Early access version 172 to play around with JShell. When I tried to open a simple java file and execute it after adding it as a snippet, it just showed modified class Test and increased the snippet number. Can you please help me realize where I went wrong?

|  Welcome to JShell -- Version 9-ea
|  For an introduction type: /help intro

jshell> /open G:\kavitha\Test.java

jshell> /list

   1 : public class Test{
        public static void main(String[] args){
                 int i = 1;
                 int j = 2;
             System.out.println("Sum of 1 and 2 is : " + (i+j));
        }
       }

jshell> /1
public class Test{
        public static void main(String[] args){
                 int i = 1;
                 int j = 2;
             System.out.println("Sum of 1 and 2 is : " + (i+j));
        }
}
|  modified class Test

jshell> /list

   2 : public class Test{
        public static void main(String[] args){
                 int i = 1;
                 int j = 2;
             System.out.println("Sum of 1 and 2 is : " + (i+j));
        }
       }
like image 866
Kavitha Karunakaran Avatar asked Jun 06 '17 20:06

Kavitha Karunakaran


1 Answers

/open only loads the file, after that you have to tell jshell what you want to execute.

Example:

jshell> /open Test.java

jshell> /list

   1 : class Test {
           public static void main(String[] args) {
               System.out.println("Hello Kavitha");
           }
           int rollDice() {
               return 1 + (int)(6 * Math.random());
           }
       }

jshell> Test.main(new String[0])
Hello Kavitha

jshell> new Test().rollDice()
$3 ==> 3

Here I have executed main method, but I can also use the loaded class as I want, create a new instance, invoke a method, etc.

Shortcut /<id> re-runs snippet with that id. In your case, snippet 1 only loads the class and executes nothing, so by executing /1 you re-loaded the same class, again without executing it.

After running my example above, /2 would re-run the main method, and /3 would re-roll the dice:

jshell> /3
new Test().rollDice()
$4 ==> 1

jshell> /3
new Test().rollDice()
$5 ==> 6

jshell> /3
new Test().rollDice()
$6 ==> 2

Addendum: /open & compilation, class loading, class initialization

(Trying to clarify why /open did not execute the main method of your class, and to show that it makes sense)

When you /open a file, JShell will add the content of the file as if you typed it into the shell.

It will then compile the snippet(s), but it will not initialize classes if there were any.

(I'm not sure whether or not if will load classes, which is the step before initialization, it's difficult to tell, see this post that was an attempt to explore the internals of JShell, it shows how class names in JShell are translated for the user, and failed attempts to see the list of loaded classes -- but that matters less than compilation & initialization)

If I open SnippetWithError.txt which contains the following:

System.out.println("Hey")
class Foo { int n=33; } bar

(yes it does not need to be a java file, it's really a bunch of text you include in the shell for evaluation)

jshell> /open SnippetWithError.txt
Hey
|  Error:
|  cannot find symbol
|    symbol:   variable bar
|   bar
|   ^-^

See it printed "Hey", and it has included class Foo:

jshell> new Foo().n
$2 ==> 33

So, JShell compiles when you /open, it executes the statements, but if some statements are class or method declarations, it does not execute those, it does not even initialize the classes.

See below how the imports are counted as separate statements in the history, then the class declaration is in its own statement (#3):

jshell> /open HasStaticInitBlock.java

jshell> /list

1 : import java.time.Duration;
2 : import java.time.Instant;
3 : class HasStaticInitBlock {
        static Instant t0 = Instant.now();
        static {
            System.out.println("Class initialized at " + t0);
        }
        static Duration timeSinceInit() {
            return Duration.between(t0, Instant.now());
        }
    }

jshell> HasStaticInitBlock.timeSinceInit()
Class initialized at 2017-06-07T06:49:06.746185Z
$4 ==> PT0.040414S

jshell> HasStaticInitBlock.timeSinceInit()
$5 ==> PT2.343019S

Class initialization was only performed when needed.

like image 123
Hugues M. Avatar answered Oct 15 '22 05:10

Hugues M.