五、Java 9 新特性 – REPL ( JShell )

REPL ,全称 Read Eval Print Loop ,中文 「 交互式解释器 」,其实,就是一种代码所见即所得的即时编译器

Java 9 引入了 REPL ,并将其命令为 「 JShell 」 ,这真是我们 Java 开发的福音,以后演示代码的时候再也不用搬着一个 IDE 到处跑了

对于我们 Java 开发者来说,应该是 Java 9 带来的最大的个性吧。我们终于可以像 Python 、 Ruby 和 Node.js 那样在 Shell 可见即可得的运行一些范例代码了

也就是说,使用 REPL,我们可以编写和测试基于 Java 的逻辑,无需使用 javac 进行编译,直接查看计算结果

运行 JShell

打开命令行提示符 ( Window 7 / Window xp ) 或 PowerShell ( Window 8 / Window 10 ) 或终端 ( Linux / Mac OSX ) ,并输入 jshell 进入 JShell。启动过程有点缓慢

[penglei@ddkk.com greeting]$ jshell
|  欢迎使用 JShell -- 版本 10.0.2
|  要大致了解该版本, 请键入: /help intro
jshell>

正如提示那样,我们可以输入 /help 来获得一些帮助

注意: 千万不要省略开头的反斜杠 /

jshell> /help
|  键入 Java 语言表达式, 语句或声明。
|  或者键入以下命令之一:
|  /list [<名称或 id>|-all|-start]
|   列出您键入的源
|  /edit <名称或 id>
|   编辑源条目
|  /drop <名称或 id>
|   删除源条目
|  /save [-all|-history|-start] <文件>
|   将片段源保存到文件
|  /open <file>
|   打开文件作为源输入
|  /vars [<名称或 id>|-all|-start]
|   列出已声明变量及其值
|  /methods [<名称或 id>|-all|-start]
|   列出已声明方法及其签名
|  /types [<名称或 id>|-all|-start]
|   列出类型声明
|  /imports 
|   列出导入的项
|  /exit [<integer-expression-snippet>]
|   退出 jshell 工具
|  /env [-class-path <路径>] [-module-path <路径>] [-add-modules <模块>] ...
|   查看或更改评估上下文
|  /reset [-class-path <路径>] [-module-path <路径>] [-add-modules <模块>]...
|   重置 jshell 工具
|  /reload [-restore] [-quiet] [-class-path <路径>] [-module-path <路径>]...
|   重置和重放相关历史记录 -- 当前历史记录或上一个历史记录 (-restore)
|  /history 
|   您键入的内容的历史记录
|  /help [<command>|<subject>]
|   获取有关使用 jshell 工具的信息
|  /set editor|start|feedback|mode|prompt|truncation|format ...
|   设置配置信息
|  /? [<command>|<subject>]
|   获取有关使用 jshell 工具的信息
|  /! 
|   重新运行上一个片段 -- 请参阅 /help rerun
|  /<id> 
|   按 ID 或 ID 范围重新运行片段 -- 参见 /help rerun
|  /-<n> 
|   重新运行以前的第 n 个片段 -- 请参阅 /help rerun
|  
|  有关详细信息, 请键入 '/help', 后跟
|  命令或主题的名称。
|  例如 '/help /list' 或 '/help intro'。主题:
|  
|  intro
|   jshell 工具的简介
|  id
|   片段 ID 以及如何使用它们的说明
|  shortcuts
|   片段和命令输入提示, 信息访问以及
|   自动代码生成的按键说明
|  context
|   /env /reload 和 /reset 的评估上下文选项的说明
|  rerun
|   重新评估以前输入片段的方法的说明
jshell> 

JShell 的中文化还是做的比较好的,提示都是引文,我们就不一一介绍了

如果要查看某个具体的命令的帮助信息,可以输入 /help [command] 来获得,比如 /help intro 获取工具简介

jshell> /help intro
|  
|                                   intro
|                                   =====
|  
|  使用 jshell 工具可以执行 Java 代码,从而立即获取结果。
|  您可以输入 Java 定义(变量、方法、类等等),例如:int x = 8
|  或 Java 表达式,例如:x + x
|  或 Java 语句或导入。
|  这些小块的 Java 代码称为“片段”。
|  
|  这些 jshell 工具命令还可以让您了解和
|  控制您正在执行的操作,例如:/list
|  
|  有关命令的列表,请执行:/help

查看 JShell 默认导入哪些包

我们可以使用 /imports 命令查看 JShell 默认导入了哪些包

jshell> /imports
|    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.*

使用 JShell import 命令导入某个包或文件

我们可以使用 import 命令导入某个类或包,就像我们代码中使用的那样

jshell> import java.lang.*
jshell> /imports
|    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.*
|    import java.lang.*

使用 JShell 进行一些简单的数学运算

JShell 默认支持一些简单的数学运算符,例如

jshell> 6 * 8
$4 ==> 48
jshell> 12 / 3
$5 ==> 4
jshell> $4
$4 ==> 48
jshell> $4 * $5
$7 ==> 192
jshell> 

可以看到,JShell 会将每一此执行的结果保存到一个以 $ 开始的变量中,而后面,我们就可以对这些变量进行引用

JShell 中默认的上下文

我么可以在 JShell 中使用我们平时在 Java 中使用的类和方法来获取当前的运行上下文

获取当前的执行线程

jshell> Thread.currentThread()
$8 ==> Thread[main,5,main]

获取当前执行的方法名

jshell> Thread.currentThread().getStackTrace()[2].getMethodName()
$9 ==> "invoke0"

获取当前执行的类名

jshell> Thread.currentThread().getStackTrace()[2].getClassName();
$10 ==> "jdk.internal.reflect.NativeMethodAccessorImpl"

在 JShell 中定义一些方法

因为内部方法和内部类的关系,我们还可以在 JShell 中定义一个方法

在一行内定义

jshell> int doubled(int i){ return i*2;}
|  已创建 方法 doubled(int)

在多行定义

jshell> int add(int i,int j){
   ...> return i+j;
   ...> }
|  已创建 方法 add(int,int)

多行定义一个方法要遵循一条准则,就是每个换行位置必须是大括号或者双目运算符等表达式的内部换行才可以

我们还可以重写之前定义的方法

jshell> int doubled(int i){ return i*2;}
|  已修改 方法 doubled(int)

定义了方法之后,我们就可以调用这些方法了

jshell> doubled(8)
$15 ==> 16
jshell> add(4,13)
$16 ==> 17

退出 JShell

如果要退出 JShell,只能输入 /exit 命令

jshell> /exit
|  再见
[penglei@ddkk.com greeting]$ 

输入exit 或按下 CTRL + C 键是没有任何效果的

jshell> exit
|  错误:
|  找不到符号
|    符号:   变量 exit
|    位置: 类 
|  exit
|  ^--^
jshell> 
jshell> 
jshell>