1. 程式人生 > >關於 JDK 9 中的 JShell,你應該瞭解的 10 件事

關於 JDK 9 中的 JShell,你應該瞭解的 10 件事

開發十年,就只剩下這套架構體系了! >>>   

JShell 是在 JDK 9 中首次引入的,以 Kulla 實現的 Java Enhancement Proposal (JEP) 222 規範的一部分。很多程式語言如 JavaScript、Python、Ruby 等,提供了非常易用的命令列執行工具,但 Java 一直缺失此功能。因此 JDK 9 引入了 Java shell 工具 —— JShell。

在之前的 文章 中我們曾經討論了 JShell 的一些基礎知識,這篇文字中我們主要聊一些高階的概念。

1. 變數重新定義

在 Java 中,我們是沒法對一個變數進行重新宣告的。但是有了 JShell,我們可以隨時在需要的時候對一個變數重新進行定義,包括原生型別以及引用型別變數。

示例:

jshell> String str="Hello"
str ==> "JShell"
jshell> Integer str=10
str ==> 10

2. Scratch 變數(怎麼翻譯好呢?)

在 JShell 命令列中可以將任意表達式計算的結果賦值給變數,儘管你並沒有顯式的賦值。這樣的變數稱為 Scratch 變數。例如:

jshell> "Hello"+"JShell"
$1 ==> "HelloJShell"

請注意為了讓 JShell 知道變數型別以及表示式計算的詳細資訊,我們可以設定 feeback 為詳細模式:

/set feedback verbose
jshell> 60+10
$2 ==> 70
|  created scratch variable $21 : int

要退出詳細模式,只需轉回正常模式即可:

/set feedback normal

3. JShell 的前向引用 ( Forward referencing )

JShell 的前向引用 (Forward referencing) 可以讓你在未定義某些方法時仍然可以呼叫。例如,假設我們有一個名為 greet() 的方法(如下所示)。而 greet() 內部呼叫了另外一個尚未定義 greetHelloWorld() 方法,這種情況下我們仍可以正確的建立 greet() 方法,但只有在 greetHelloWorld 方法建立後才可以被呼叫。這就是 JShell 的前向引用。

示例:

jshell> public void greet(){
...> greetHelloWorld();}
|  created method greet(), however, it cannot be invoked until method greetHelloWorld() is declared               jshell> greet()
|  attempted to call method greet() which cannot be invoked until method greetHelloWorld() is declared
jshell> public void greetHelloWorld(){
...> System.out.println("Hello World");}
|  created method greetHelloWorld()
jshell> greet()
Hello World

4. JShell 的異常處理

示例:

jshell> int divide(int a,int b) throws IOException{
...> if(b==0){
...> throw new IOException();
...> }
...> return a/b;
...> }
|  created method divide(int,int)
jshell> divide(1,0)
|  java.io.IOException thrown:
|        at divide (#2:3)
|        at (#3:1)

注意這裡我們並沒有捕獲任何關於 divide 方法的異常,但是 JShell 會幫我們處理好。同時這裡我們也沒有引入 IOException 類,但程式碼的編譯和執行都沒有任何問題。原因是 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.*
|    import java.io.IOException

5. JShell 會話的指令持久化行為

預設情況下 JShell 會話中的所有指令都是不被持久化的,這些指令是易失的,當用戶退出 JShell 會話時就會丟失。

但是 JShell 提供了在特定的會話中儲存所有指令資訊的方法,你可以在另外一個新的會話中使用這些指令。當用戶需要儲存一些有用的程式碼片段時候,這個功能是很好用的。

示例:

 

jshell> String s="Hello"
s ==> "Hello"

jshell> int i=100;
i ==> 100
jshell> /save C:\data\mySession.jsh
jshell> /exit
|  Goodbye

λ jshell
|  Welcome to JShell -- Version 9.0.4
|  For an introduction type: /help intro
jshell> /vars
jshell> /open C:\Data\mySession.jsh
jshell> /vars
|    String s = "Hello"
|    int i = 100

6. 使用外部庫

有很多的第三方開源庫,一般開發者需要將這些庫放到專案的類路徑才可以使用。但是在 JShell 中,使用這些三方庫更簡單。

例如我們想使用 Apache Commons Lang 中的字串工具包,可以使用如下語法來使用第三方庫包:

(譯者注:其實並沒有那麼方便)

shell> /env --class-path <Relative Path of lib from where JShell is run>
jshell> /env --class-path ../lib/commons-lang3-3.8.1.jar
|  Setting new options and restoring state.
import org.apache.commons.lang3.StringUtils;
jshell> System.out.println(StringUtils.isEmpty(""))
true
jshell> System.out.println(StringUtils.isEmpty("hello"))
false

7. 使用專門的 JShell 命令和工具來加速開發

JShell 包含很多很有用的命令,這些方法可以加速程式碼的測試,例如:

 /history - Prints all commands executed on JShell (Java Commands+ JShell specific commands)

示例:

jshell> String s ="Hello"
s ==> "Hello"

jshell> class Employee{
...> }
|  created class Employee

jshell> /vars
|    String s = "Hello"

jshell> /history
String s ="Hello"
class Employee{
}
/vars
/history
 /list    - Prints all JAVA related commands executed in JShell. Notice that this list the command in Numerical              order of each command identifier. This identifier can be used to execute certain construct again.

示例:

jshell> /list
1 : String s ="Hello";
2 : class Employee{
}
jshell> /1
String s ="Hello";
s ==> "Hello"
/reset   - Resets the state of current JShell session.
CTRL+R   - For searching a particular command
CTRL+S   - Performing Forward Search
CTRL+C   - To exit from JShell session
/exit    - To exit from JShell session
/vars     - To list all variables inside current JShell session
/imports  - To list all imports inside current JShell session
/help    - To know more about JShell specific commands

8. JShell 使用 Tab 鍵自動完成

JShell 可以使用 Tab 鍵來達到程式碼自動完成的功能。

示例:

除了這些,你還可以在 JShell 中檢視相關包的文件:

jshell> java.io
io
Signatures:
java.io
<press tab again to see documentation>

9. 編輯已執行命令

在開發過程中我們經常會需要修改之前執行的命令,JShell 可以很方便的實現。

示例:

/edit        - Edit all constructs in current JShell session
/edit 1      - Edit only 1st construct (see from /list) in current JShell session
/edit Person - Edit only Person class in current JShell session

10. 如何對 JShell 擴充套件程式設計

JDK 提供 API 用來訪問 JShell ,這些 API 可以瀏覽 JavaDoc 瞭解詳情。

這篇文字裡我們介紹了一些 JShell 的高階特性,但這並非全部,建議開發者通過 JShell 的文件瞭解更多資訊。

文章翻譯自:https://developers.redhat.com/blog/2019/04/05/10-things-developers-need-to-k