Java9特性预览——Jshell

来源:
三产
最后修订:
2016年06月29日 00:00:00
 336

什么是JShell?

JShell/Kulla项目是第一个官方的Java REPL (Read-Eval-Print-Loop的缩写,即交互式编程环境),是一种命令行工具。它允许你无需编写类或者方法来执行Java语句。它与Python的解释器或其它本地...

什么是JShell?

JShell/Kulla项目是第一个官方的Java REPL (Read-Eval-Print-Loop的缩写,即交互式编程环境),是一种命令行工具。它允许你无需编写类或者方法来执行Java语句。它与Python的解释器或其它本地支持REPL的JVM语言,如Scala和Groovy类似。在Java 9即将到来的的特性中,这绝对是更有趣的特性之一。

JShell的使用

命令行中直接使用

下载安装OpenJDK9,然后我们就可以在安装目录的bin文件夹下看到 jshell.exe ,如果你配置好了环境变量,那么就可以在命令行中使用了。 JShell

我们来看下Jshell可以有什么设置选项:

JShell选项

/list:用于查看你之前输入的语句的信息

/list命令

/vars:用于查看你之前输入的变量,如果你只是输入了一个表达式,Jshell会将计算结果保存为一个变量

/vars

我们并没有声明$1变量,但是Jshell默认将表达式的结果转为变量进行了存储,所以我们可以直接使用改变量: 没有声明$1

/save:存储之前的输入

我们执行: /save 会将文件存储到你的用户文件目录下(你也可以指定完整的路径) 我们来看看存储的文件的内容:

1+1
1+1
2+2
$1
System.out.print($1)

其实就是简单将你的输入进行了保存

/reset:重置,会清楚你之前输入的内容

/reset

/open:打开一个文件并执行其中内容

/open

/methods:获取声明的或者使用到静态方法

/methods

/methods详解

/types:显示接口、类、枚举等信息

/types

/imports:获取导入的包

/imports

上面的包都是默认导入的包这样我们就能直接使用这些包中的类而无需自己声明 直接使用List

/exit:退出Jshell

/exit

/reload:重置后重新加载之前的内容

/reload

/classpath <path>:这个用于你使用自己声明的类的时候可以将目录添加到classpath进行引用

/history:查看之前所有输入的命令

/history

/retain editor|start|feedback|mode 用于保存配置信息方便 别的环境中/set editor|start|feedback|mode来获得样的配置

/id:重新执行某个id的操作

/id

/-n:重新运行前面的第 n 个片段

/-n

在代码中的使用

JDK9将Jshell相关API封装为模块(模块相关知识可以查看模块化简单教程)方便使用。下面我们通过代码来学习一下相关的API:

package com.coderknock;
import java.io.ByteArrayInputStream;
import java.io.Console;
import java.util.List;
import jdk.jshell.*;
import jdk.jshell.Snippet.Status;
/**
 * 拿客
 * www.coderknock.com
 * QQ群:213732117
 * 创建时间:2016年06月29日
 * 描述:JShell
 */
public class JshellMain {
    public static void main(String[] args) {
         Console console = System.console();
         //创建一个Jshell环境,之后会自动进行关闭
         try (JShell js = JShell.create()) {
             //循环监听输出
             do {
                 System.out.print("请输入一些Java代码: ");
                 String input = console.readLine();
                 if (input == null) {
                     break;
                 }
                 //将输入的指令转化为SnippetEvent对象
                 List<SnippetEvent> events = js.eval(input);
                 for (SnippetEvent e : events) {
                     StringBuilder sb = new StringBuilder();
                     if (e.causeSnippet() == null) {
                         //  我们有一个片段创建的事件
                         switch (e.status()) {//根据代码片段的执行进行输出
                             case VALID:
                                 sb.append("Successful ");
                                 break;
                             case RECOVERABLE_DEFINED:
                                 sb.append("With unresolved references ");
                                 break;
                             case RECOVERABLE_NOT_DEFINED:
                                 sb.append("Possibly reparable, failed  ");
                                 break;
                             case REJECTED:
                                 sb.append("Failed ");
                                 break;
                         }
                         if (e.previousStatus() == Status.NONEXISTENT) {
                             sb.append("addition");
                         } else {
                             sb.append("modification");
                         }
                         sb.append(" of ");
                         sb.append(e.snippet().source());
                         System.out.println(sb);
                         if (e.value() != null) {
                             System.out.printf("Value is: %s\n", e.value());
                         }
                         System.out.flush();
                     }
                 }
             } while (true);
         }
         System.out.println("\nGoodbye");
     }
}

进行编译javac JshellMain.java -encoding UTF-8 运行结果: 运行 当输入错误的java代码时: 输入错误 执行for循环等: for循环