7

我尝试安装 JDK 9 Early access 版本 172 来玩 JShell。当我尝试打开一个简单的 java 文件并在将其添加为片段后执行它时,它只显示修改后的类 Test 并增加了片段编号。你能帮我弄清楚我哪里出错了吗?

|  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));
        }
       }
4

1 回答 1

15

/open只加载文件,之后你必须告诉 jshell 你想要执行什么。

例子:

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

这里我已经执行了main方法,但我也可以根据需要使用加载的类,创建一个新实例,调用一个方法等。

快捷方式/<id>使用该 ID 重新运行代码段。在您的情况下,片段 1 仅加载该类并且不执行任何操作,因此通过执行/1您重新加载了相同的类,再次不执行它。

运行上面的示例后,/2将重新运行 main 方法,并/3重新掷骰子:

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

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

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

附录:/open&编译、类加载、类初始化

(试图澄清为什么 /open没有执行你的类的主要方法,并表明它是有道理的)

当你/open创建一个文件时,JShell 会添加文件的内容,就像你在 shell 中键入它一样

然后它将编译代码片段,但如果有任何类,它不会初始化。

(我不确定是否会加载类,这是初始化之前的步骤,很难说,请参阅这篇试图探索 JShell 内部的帖子,它显示了 JShell 中的类名是如何翻译的用户,并且尝试查看已加载类的列表失败——但这比编译和初始化更重要)

如果我打开SnippetWithError.txt其中包含以下内容:

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

(是的,它不需要是一个 java 文件,它实际上是你在 shell 中包含用于评估的一堆文本)

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

看到它印有“嘿”,它包括类Foo

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

因此,JShell编译/open,它会执行语句,但如果某些语句是类或方法声明,它不会执行这些,甚至不会初始化类。

请参阅下面如何将导入计为历史记录中的单独语句,然后类声明在其自己的语句中(#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

类初始化仅在需要时执行。

于 2017-06-06T21:43:07.173 回答