上一章节中我们只讲解了 JShell 中的基本用法,知道了如何输入代码和如何重新定义代码片段。 JShell 的功能远远不止于此。它还提供了完整的向前引用和异常回溯机制。
向前引用
JShell 支持引用尚未定义的方法,变量或类。
这个特性非常有用,尤其是在尝试一些实验性功能的时候。它提供了一种探索性编程的方法,同时也是某些形式的编程所必须的。
例如下面的示例,我们可以先定义一个方法用于计算球体的体积,但因为某些原因,我们又没办法预先定义常量 PI
jshell> double volume(double radius) { ...> return 4.0 / 3.0 * PI * cube(radius); ...> } | 已创建 方法 volume(double), 不过, 它无法调用, 直至 variable PI, and method cube(double) 已声明
从提示信息中可以看到,我们的方法 double volume(double radius)
定义是成功的,但由于我们没有预先定义常量 PI
和另一方法 cube
所以不能调用,即使调用也会失败
jshell> volume(5.0) | 已尝试调用方法 volume(double) 它无法调用, 直至 variable PI, and method cube(double) 已声明
为了能够调用 volume()
方法,我们需要定义 PI
和 cube()
jshell> double PI = 3.1415926535 jshell> volume(5) | 已尝试调用方法 volume(double) 它无法调用, 直至 method cube(double) 已声明 jshell> double cube(double x) { return x * x * x; } jshell> volume(5) $8 ==> 523.5987755833333
从提示的结果来看,PI
和 cube()
缺一不可,少了一个都不能执行成功
此外,需要注意的是,因为我们并没有为 PI 定义任何类型,所以 volume()
还是假设 PI
是和 3.0
等相同的类型。但如果我们传递了一个比 double
更大的类型,比如 BigDecimal
,那么还是会出现一些不兼容提示的
例如下面的范例,我们给 PI
赋值了一个超级多小数位数的 BigDecimal
类型
jshell> BigDecimal PI = new BigDecimal("3.141592653589793238462643383") PI ==> 3.141592653589793238462643383 | 已替换 变量 PI : BigDecimal | 更新已修改 方法 volume(double) 它无法调用, 直至 此错误已更正: | 二元运算符 '*' 的操作数类型错误 | 第一个类型: double | 第二个类型: java.math.BigDecimal | return 4.0 / 3.0 * PI * cube(radius); | ^------------^ | 更新已覆盖 变量 PI : double
PI
的新定义与 volume()
的定义类型不兼容。因为我们出于详细信息模式,因此会显示受更改影响的其他定义的更新信息,在上面的范例中体现为描述了不兼容性。
请注意,详细模式是唯一显示更新信息的预定义反馈模式。其它返回模式中,在执行代码之前不会显示警告。这样做的目的是防止更新过载。
但在所有预定义模式下,执行 volume()
方法都会显示问题
jshell> volume(5) | 已尝试调用方法 volume(double) 它无法调用, 直至 此错误已更正: | 二元运算符 '*' 的操作数类型错误 | 第一个类型: double | 第二个类型: java.math.BigDecimal | return 4.0 / 3.0 * PI * cube(radius); | ^------------^ jshell>
JShell 中的异常
如果运行的代码发生了异常,JShell 会即时的进行异常回溯,且会反馈提示发生异常的代码段的位置。
jshell> int divide(int x, int y) { ...> return x / y; ...> } | 已创建 方法 divide(int,int) jshell> divide(5, 0) | java.lang.ArithmeticException thrown: / by zero | at divide (#15:2) | at (#16:1)
如果想要查看具体的异常回溯信息,可以使用 list
命令,如下
jshell> /list 2 : 2 + 2 4 : twice("简单教程") 5 : String twice(String s) { return "Twice:" + s; } 6 : twice("简单教程") 8 : String x = "简单教程"; 9 : double volume(double radius) { return 4.0 / 3.0 * PI * cube(radius); } 10 : double cube(double x) { return x * x * x; } 13 : BigDecimal PI = new BigDecimal("3.141592653589793238462643383"); 14 : volume(5) 15 : int divide(int x, int y) { return x / y; } 16 : divide(5, 0)
后记
这两个功能简直就是神器啊,尤其是向前回溯功能,各种姿势调戏代码都可以有么有