В Java 9 наряду с другими нововведениями появился интерпретатор команд Java. Ищите файл “jshell” в каталоге “bin” дистрибутива Java. Имейте в виду, что правильно писать JShell, а не JsHell, то есть это Java Shell, а не Javascript Hell. После запуска вы увидите следующее:
1 2 3 4 5 |
$ ./jshell | Welcome to JShell -- Version 9.0.1 | For an introduction type: /help intro jshell> |
С помощью этого интерпретатора вы можете выполнять небольшие куски Java-кода. Например:
1 2 |
jshell> System.out.println("Hello, World!"); Hello, World! |
Можно даже так (в этом случае интерпретатор неявно создаст переменную $2):
1 2 |
jshell> 2 + 10 $2 ==> 12 |
Кроме команд Java у JShell есть свои собственные команды, которые начинаются с «/». Вы можете посмотреть весь их список с помощью команды /help:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 |
jshell> /help | Type a Java language expression, statement, or declaration. | Or type one of the following commands: | /list [<name or id>|-all|-start] | list the source you have typed | /edit <name or id> | edit a source entry referenced by name or id | /drop <name or id> | delete a source entry referenced by name or id | /save [-all|-history|-start] <file> | Save snippet source to a file. | /open <file> | open a file as source input | /vars [<name or id>|-all|-start] | list the declared variables and their values | /methods [<name or id>|-all|-start] | list the declared methods and their signatures | /types [<name or id>|-all|-start] | list the declared types | /imports | list the imported items | /exit | exit jshell | /env [-class-path <path>] [-module-path <path>] [-add-modules <modules>] ... | view or change the evaluation context | /reset [-class-path <path>] [-module-path <path>] [-add-modules <modules>]... | reset jshell | /reload [-restore] [-quiet] [-class-path <path>] [-module-path <path>]... | reset and replay relevant history -- current or previous (-restore) | /history | history of what you have typed | /help [<command>|<subject>] | get information about jshell | /set editor|start|feedback|mode|prompt|truncation|format ... | set jshell configuration information | /? [<command>|<subject>] | get information about jshell | /! | re-run last snippet | /<id> | re-run snippet by id | /-<n> | re-run n-th previous snippet | | For more information type '/help' followed by the name of a | command or a subject. | For example '/help /list' or '/help intro'. | | Subjects: | | intro | an introduction to the jshell tool | shortcuts | a description of keystrokes for snippet and command completion, | information access, and automatic code generation | context | the evaluation context options for /env /reload and /reset jshell> |
Команда /list позволяет увидеть список фрагментов кода, которые мы вводили:
1 2 3 4 |
jshell> /list 1 : System.out.println("Hello, World!"); 2 : 2 + 10 |
Затем вы можете отредактировать любой из этих кусков во внешнем редакторе по id:
1 |
jshell> /edit 2 |
Откроется редактор, где вы можете поменять этот кусок кода:

Если вы отредактируете и кликните по кнопке “Accept”, то JShell выполнит введённый вами в JShell Edit Pad код. Можно задать свой редактор, например следующая команда укажет, что нужно использовать Scratch:
1 |
jshell> /set editor scratch-text-editor |
После нескольких правок командой
1 |
/edit |
у меня получилось так:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
jshell> /edit 2 Edited snipped 8.0 jshell> /list 1 : System.out.println("Hello, World!"); 2 : 2 + 10 3 : System.out.println("Edited snipped " + Math.pow(2.0, 3.0)); jshell> /list 1 : System.out.println("Hello, World!"); 2 : 2 + 10 3 : System.out.println("Edited snipped " + Math.pow(2.0, 3.0)); jshell> /edit 3 $4 ==> 11 jshell> /list 1 : System.out.println("Hello, World!"); 2 : 2 + 10 3 : System.out.println("Edited snipped " + Math.pow(2.0, 3.0)); 4 : 2 + 10 - 1 |
Команда /drop удаляет кусок кода из списка:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
jshell> /list 1 : System.out.println("Hello, World!"); 2 : 2 + 10 3 : System.out.println("Edited snipped " + Math.pow(2.0, 3.0)); 4 : 2 + 10 - 1 jshell> /drop 3 jshell> /list 1 : System.out.println("Hello, World!"); 2 : 2 + 10 4 : 2 + 10 - 1 |
При работе JShell перед каждым своим стартом выполняет определённый код, который можно посмотреть командой /list -start:
1 2 3 4 5 6 7 8 9 10 11 12 |
jshell> /list -start s1 : import java.io.*; s2 : import java.math.*; s3 : import java.net.*; s4 : import java.nio.file.*; s5 : import java.util.*; s6 : import java.util.concurrent.*; s7 : import java.util.function.*; s8 : import java.util.prefs.*; s9 : import java.util.regex.*; s10 : import java.util.stream.*; |
Сейчас там только import-ы, но мы можем добавить туда другие команды с помощью /set start с последующим вызовом /reset. Подробнее про это вы можете узнать набрав команду
1 |
/help /set start |
В качестве примера можем использовать вот такой файл “myjshellstart.txt”:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
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 javax.swing.*; import javax.crypto.*; String createHelloString(String name) { return "Hello, " + name; } |
Используем его в качестве стартового:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
jshell> /list -start s1 : import java.io.*; s2 : import java.math.*; s3 : import java.net.*; s4 : import java.nio.file.*; s5 : import java.util.*; s6 : import java.util.concurrent.*; s7 : import java.util.function.*; s8 : import java.util.prefs.*; s9 : import java.util.regex.*; s10 : import java.util.stream.*; jshell> /set start ~/myjshellstart.txt jshell> /reset | Resetting state. jshell> /list -start s1 : import java.io.*; s2 : import java.math.*; s3 : import java.net.*; s4 : import java.nio.file.*; s5 : import java.util.*; s6 : import java.util.concurrent.*; s7 : import java.util.function.*; s8 : import java.util.prefs.*; s9 : import java.util.regex.*; s10 : import java.util.stream.*; s11 : import javax.swing.*; s12 : import javax.crypto.*; s13 : String createHelloString(String name) { return "Hello, " + name; } jshell> |
Заданный таким образом стартовый код будет работать только в этом сеансе JShell, чтобы сохранить его для следующих запусков выполните команду:
1 |
jshell> /set start -retain |
Список подключаемых пакетов к вашим фрагментам кода показывает команда /imports:
1 2 3 4 5 6 7 8 9 10 11 |
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-ы можно добавить просто подключив нужный пакет или класс:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
jshell> import java.awt.Image 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 javax.swing.* | import javax.crypto.* | import java.awt.Image |
Команда /vars показывает список объявленных переменных:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
jshell> /vars | int $2 = 12 | int $4 = 11 jshell> int var1 = 10; var1 ==> 10 jshell> String str1 = "MyString"; str1 ==> "MyString" jshell> /vars | int $2 = 12 | int $4 = 11 | int var1 = 10 | String str1 = "MyString" |
Команды /save <имя_файла> и /open позволяют сохранять выполненные команды и выполнять команды из файла, так что вы можете сохранять наработанные куски кода для будущего использования.
Пример:
1 2 3 4 5 6 7 |
jshell> System.out.println("Hello, World!"); Hello, World! jshell> 3.14 * 3 / 56 + 145 $2 ==> 145.1682142857143 jshell> /save ~/mycommands.txt |
В файле “mycommands.txt” окажутся все ваши команды:
1 2 |
System.out.println("Hello, World!"); 3.14 * 3 / 56 + 145 |
Выполним команды из файла:
1 2 |
jshell> /open ~/mycommands.txt Hello, World! |
JShell может выполнять довольно таки большие и осмысленные куски кода. Вы можете объявлять новые классы, интерфейсы и перечисления. Команда /types выводит список объявленных вами типов:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
jshell> class Monster { ...> private int ammo; ...> private double health; ...> public void takeHit(double damage) { ...> this.health -= damage; ...> } ...> } | created class Monster jshell> /types | class Monster jshell> interface Devil {} | created interface Devil jshell> /types | class Monster | interface Devil jshell> enum Liveness { ...> ALIVE, ...> DEAD ...> } | created enum Liveness jshell> /types | class Monster | interface Devil | enum Liveness |
JShell позволяет объявлять методы без привязки к какому-либо классу. Вполне возможно, что внутри себя он всё же куда-дто их привязывает, но мне так и не удалось найти в интернете информацию по этому вопросу. Команда /methods отображает список созданных методов:
1 2 3 4 5 6 7 8 |
jshell> String amIWithoutAnyClass(String str1, int v1) { ...> return str1 + v1; ...> } | created method amIWithoutAnyClass(String,int) jshell> /methods | String createHelloString(String) | String amIWithoutAnyClass(String,int) |
Команда /! повторяет предыдущий выполненный кусок кода:
1 2 3 4 5 6 7 8 9 |
jshell> int n = 10; n ==> 10 jshell> System.out.println(++n); 11 jshell> /! System.out.println(++n); 12 |
При вводе своих фрагментов кода вы всегда можете использовать клавишу табуляции для автодополнения. Если вариантов автодополнения несколько, то все они выведутся на экран.
Также есть очень полезная возможность автоматически импортировать необходимые классы при наборе кусков кода. Например, вы можете набрать System.out.println(Paths, затем нажать комбинацию клавиш «Shift + Tab», затем клавишу «i». Появится список выборка. Нажмите клавишу с цифрой «1» на клавиатуре, чтобы импортировать класс (1: import: java.nio.file.Paths):
1 2 3 4 5 6 7 8 |
jshell> System.out.println(Paths 0: Do nothing 1: import: java.nio.file.Paths Choice: Imported: java.nio.file.Paths jshell> System.out.println(Paths.get("directory", "subdirectory")); directory/subdirectory |
Есть способ облегчения объявления переменных. Введите 234+56 и нажмите комбинацию «Shift + Tab», а затем клавишу «v». Компилятор заботливо допишет объявление переменной и подставит курсор в место ввода её наименования:
1 2 3 4 5 |
jshell> 234+56 jshell> int = 234+56 ^ | Курсор будет здесь |
И напоследок осталось самое главное, выход из консоли JShell осуществляется командой /exit :
1 2 |
jshell> /exit | Goodbye |