问题
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));
}
}
回答1:
/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.
来源:https://stackoverflow.com/questions/44399338/how-to-run-a-whole-java-file-added-as-a-snippet-in-jshell