JShell 让你不写类、不写 main 就能验证一个想法。它怎么处理前向引用、重新定义、错误和异常?怎么用它试第三方库?它的 API 能做什么?这篇用 jshell 命令行与 jdk.jshell API 逐项真实运行。
jshell> $1 ==> 2 jshell> $2 ==> 6 jshell> $3 ==> 3 jshell> x ==> 10 jshell> $5 ==> 20 jshell> x ==> "now a string" jshell> x ==> "now a string" jshell> d ==> 0.0 jshell> big ==> -2147483648
jshell> | created method f(), however, it cannot be invoked until method g() is declared jshell> | attempted to call method f() which cannot be invoked until method g() is declared jshell> | created method g() jshell> $4 ==> 42 jshell> | modified method g() jshell> $6 ==> 101 jshell> | Error: | incompatible types: java.lang.String cannot be converted to int | int y = "bad"; | ^---^ jshell> | created method h(), however, it cannot be invoked until variable undefinedVar is declared jshell> | Exception java.lang.ArithmeticException: / by zero | at (#8:1) jshell> z ==> 0 jshell> | Exception java.lang.RuntimeException: boom | at (#10:1) jshell> sx ==> 1 jshell> px ==> 2 jshell> fx ==> 3 jshell> sx ==> 5 jshell> | Goodbye
jshell> a ==> 1
jshell> s ==> "x"
jshell> | created method twice(int)
jshell> | created class P
jshell> | created interface I
jshell> | created enum E
jshell> | created record R
jshell> | int a = 1
| String s = "x"
jshell> | int twice(int)
jshell> | class P
| interface I
| enum E
| record R
jshell> | 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>
1 : int a = 1;
2 : String s = "x";
3 : int twice(int n) { return n * 2; }
4 : class P { int v; }
5 : interface I {}
6 : enum E { A, B }
7 : record R(int q) {}
jshell> | dropped method twice(int)
jshell>
jshell> | Resetting state.
jshell>
jshell> | Goodbye jshell 启动并计算 1+1 再退出:1038 ms(5 次中位);对照 java -version 26 ms
默认导入(/imports): | 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.*
--class-path 加载 guava:
jshell> l ==> [3, 1, 2]
jshell> $3 ==> [1, 2, 3]
不给 --class-path 导入 guava: jshell> | Error: | | package com.google.common.collect does not exist | jshell> | Error:
jshell -s(静默反馈)下 println 的输出: -> hi | -> line1 | -> int a = 6 → kind=VAR status=VALID value=6
a * 7 → kind=VAR status=VALID value=42
int f() { return h() + 1; } → kind=METHOD status=RECOVERABLE_DEFINED value=null
int h() { return 41; } → kind=METHOD status=VALID value=null
int h() { return 41; } → kind=METHOD status=VALID value=null
f() → kind=VAR status=VALID value=42
int a = "x"; → kind=VAR status=REJECTED value=null,诊断:incompatible types: java.lang.String cannot be converted to int
int a = "x"; → kind=VAR status=OVERWRITTEN value=null
String s = null; s.length() → kind=VAR status=VALID value=null
String s = null; s.length() → kind=VAR status=VALID value=null,异常 EvalException(java.lang.NullPointerException)
class C { int m() { return 1; } } → kind=TYPE_DECL status=VALID value=null
new C().m() → kind=VAR status=VALID value=1
int a = 6; → kind=VAR status=VALID value=6
a * 7; → kind=VAR status=VALID value=42
jshell 里的变量与方法:[$1:int, $2:int, s:String, $3:int, $4:int, a:int, $5:int] [f()int, h()int]
无限循环 while (true) 在 500 ms 后被 js.stop() 中断:状态 VALID,异常 无,耗时 509 ms
中断之后会话还能用:eval("n > 0") = true
来自 jshell 的标准输出
static int sx = 1; → status=VALID,诊断:[]
final int fx = 2; → status=VALID,诊断:[]
private int px = 3; → status=VALID,诊断:[]
public int qx = 4; → status=VALID,诊断:[]