Contents

Java 9 REPL

1. 简介

本文是关于jshell的,这是一个交互式REPL(读取-评估-打印-循环)控制台,它与 JDK 捆绑在一起,用于即将发布的 Java 9 版本。对于那些不熟悉这个概念的人,REPL 允许交互式地运行任意代码片段并评估它们的结果。 REPL 可用于诸如快速检查想法的可行性或找出例如StringSimpleDateFormat的格式化字符串之类的事情。

2. REPL

要开始,我们需要运行 REPL,这是通过调用来完成的:

$JAVA_HOME/bin/jshell

如果需要来自 shell 的更详细的消息传递,可以使用*-v*标志:

$JAVA_HOME/bin/jshell -v

一旦准备就绪,我们将在底部收到友好的消息和熟悉的 Unix 风格提示。

3. 定义和调用方法

可以通过输入方法的签名和正文来添加方法:

jshell> void helloWorld() { System.out.println("Hello world");}
|  created method helloWorld()

在这里,我们定义了无处不在的“hello world”方法。可以使用普通的 Java 语法调用它:

jshell> helloWorld()
Hello world

4.变量

可以使用普通的 Java 声明语法定义变量:

jshell> int i = 0;
i ==> 0
|  created variable i : int
jshell> String company = "Blogdemo"
company ==> "Blogdemo"
|  created variable company : String
jshell> Date date = new Date()
date ==> Sun Feb 26 06:30:16 EST 2017
|  created variable date : Date

请注意,分号是可选的。变量也可以在没有初始化的情况下声明:

jshell> File file
file ==> null
|  created variable file : File

5. 表达式

接受任何有效的 Java 表达式并显示评估结果。如果没有提供结果的明确接收者,将创建“scratch”变量:

jshell> String.format("%d of bottles of beer", 100)
$6 ==> "100 of bottles of beer"
|  created scratch variable $6 : String

REPL 在这里非常有用,它告诉我们它创建了一个名为*$6的临时变量,其值是“墙上有 100 瓶啤酒”,它的类型是String*。 多行表达式也是可能的。Jshell足够聪明,可以知道表达式何时不完整,并会提示用户继续换行:

jshell> int i =
   ...> 5;
i ==> 5
|  modified variable i : int
|    update overwrote variable i : int

请注意提示如何更改为缩进的*…>*以表示表达式的继续。

6. 命令

Jshell 提供了很多与评估 Java 语句无关的元命令。它们都以正斜杠 (/) 开头,以区别于正常操作。例如,我们可以通过发出*/help*或 /?请求所有可用命令的列表。 让我们来看看其中的一些。

6.1. import

要列出当前会话中活动的所有导入,我们可以使用*/import*命令:

jshell> /import
|    import java.io.*
|    import java.math.*
|    import java.net.*
|    import java.nio.file.*
|    import java.util.*
|    import java.util.concurrent.*
|    import java.util.function.*
|    import java.util.prefs.*
|    import java.util.regex.*
|    import java.util.stream.*

正如我们所看到的,shell 开始时已经添加了很多有用的导入。

6.2. 列表

在 REPL 中工作并不像在我们的指尖拥有一个功能齐全的 IDE 那样容易:很容易忘记哪些变量具有哪些值,定义了哪些方法等等。要检查 shell 的状态,我们可以使用*/var*、/methods/list或*/history*:

jshell> /var
| int i = 0
| String company = "Blogdemo"
| Date date = Sun Feb 26 06:30:16 EST 2017
| File file = null
| String $6 = "100 of bottles of beer on the wall"
jshell> /methods
| void helloWorld()
jshell> /list
 1 : void helloWorld() { System.out.println("Hello world");}
 2 : int i = 0;
 3 : String company = "Blogdemo";
 4 : Date date = new Date();
 5 : File file;
 6 : String.format("%d of bottles of beer on the wall", 100)
jshell> /history
void helloWorld() { System.out.println("Hello world");}
int i = 0;
String company = "Blogdemo"
Date date = new Date()
File file
String.format("%d of bottles of beer on the wall", 100)
/var
/methods
/list
/history

/list和*/history*的区别在于后者除了显示表达式之外还显示命令。

6.3. 保存

要保存表达式历史,可以使用*/save*命令:

jshell> /save repl.java

这会将我们的表达式历史记录保存到我们运行jshell命令的同一目录中的repl.java中。

6.4. 正在加载

要加载以前保存的文件,我们可以使用*/open*命令:

jshell> /open repl.java

然后可以通过发出*/var*、/method或*/list*来验证加载的会话。

6.5.退出

完成工作后,/exit命令可以终止 shell:

jshell> /exit
|  Goodbye

再见jshell