简体   繁体   English

如何在JShell中运行作为片段添加的整个Java文件?

[英]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. 我尝试安装JDK 9 Early access version 172来玩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. 当我尝试打开一个简单的java文件并在将其添加为片段后执行它时,它只显示了修改后的类Test并增加了片段编号。 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));
        }
       }

/open only loads the file, after that you have to tell jshell what you want to execute. /open只加载文件,之后你必须告诉jshell你想要执行什么。

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. 这里我已经执行了main方法,但我也可以根据需要使用加载的类,创建新实例,调用方法等。

Shortcut /<id> re-runs snippet with that id. 快捷方式/<id>重新运行该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. 在您的情况下,代码片段1仅加载类并且不执行任何操作,因此通过执行/1您重新加载相同的类,同样不再执行它。

After running my example above, /2 would re-run the main method, and /3 would re-roll the dice: 运行上面的示例后, /2将重新运行main方法,并且/3将重新掷骰子:

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 附录: /open &compilation,类加载,类初始化

(Trying to clarify why /open did not execute the main method of your class, and to show that it makes sense) (试图澄清为什么 /open没有执行你的类的主要方法,并表明它是有道理的)

When you /open a file, JShell will add the content of the file as if you typed it into the shell . 当您/open文件时,JShell将添加文件的内容, 就像您将其键入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) (我不确定是否会加载类,这是初始化之前的步骤,很难说,看到这篇文章试图探索JShell的内部,它展示了如何翻译JShell中的类名称用户,并且尝试查看已加载的类列表失败 - 但这比编译和初始化更重要

If I open SnippetWithError.txt which contains the following: 如果我打开包含以下内容的SnippetWithError.txt

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) (是的,它不需要是一个java文件,它实际上是你在shell中包含的一堆文本用于评估)

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

See it printed "Hey", and it has included class Foo : 看到它打印“嘿”,它包括类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. 因此,JShell在你/open编译 ,它执行语句,但是如果某些语句是类或方法声明,它不会执行那些,它甚至不会初始化类。

See below how the imports are counted as separate statements in the history, then the class declaration is in its own statement (#3): 请参阅下面如何将导入计入历史记录中的单独语句,然后类声明在其自己的语句中(#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. 只在需要时才执行类初始化。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM