Пакет jdk.jshell
JShell — центральный класс. Экземпляр JShell хранит состояние вычислений, включающее текущий набор исходных фрагментов и созданное ими состояние выполнения.
Каждый исходный фрагмент представлен экземпляром подкласса Snippet. Например, оператор представлен экземпляром StatementSnippet, а объявление метода — экземпляром MethodSnippet. Фрагменты создаются при вызове JShell.eval(String) с входными данными, содержащими один или несколько фрагментов кода.
О каждом изменении состояния компиляции фрагмента сообщается с помощью SnippetEvent. Существует три основных типа изменений состояния фрагмента: он может быть создан с помощью eval, удалён из активного состояния исходного кода с помощью JShell.drop(jdk.jshell.Snippet) или его состояние может обновиться вследствие изменения состояния другого фрагмента. Например, если заданы js, экземпляр JShell, выполнение js.eval("int x = 5;") добавит переменную x в состояние исходного кода и создаст событие, описывающее создание VarSnippet для x. Затем выполнение js.eval("int timesx(int val) { return val * x; }") добавит метод в состояние исходного кода и создаст событие, описывающее создание MethodSnippet для timesx. Предположим, что varx содержит фрагмент, созданный первым вызовом eval. Выполнение js.drop(varx) создаст два события: одно — об изменении состояния фрагмента переменной на DROPPED, другое — об обновлении фрагмента метода (который теперь содержит неразрешённую ссылку на x).
Разумеется, при общем использовании API входные данные не будут фиксированными строками, а будут поступать от пользователя. Ниже приведён очень упрощённый пример того, как API можно использовать для реализации REPL.
import java.io.ByteArrayInputStream;
import java.io.Console;
import java.util.List;
import jdk.jshell.*;
import jdk.jshell.Snippet.Status;
class ExampleJShell {
public static void main(String[] args) {
Console console = System.console();
try (JShell js = JShell.create()) {
do {
System.out.print("Enter some Java code: ");
String input = console.readLine();
if (input == null) {
break;
}
List<SnippetEvent> events = js.eval(input);
for (SnippetEvent e : events) {
StringBuilder sb = new StringBuilder();
if (e.causeSnippet() == null) {
// We have a snippet creation event
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");
}
}
Чтобы подписаться на события изменения состояния, используйте JShell.onSnippetEvent(java.util.function.Consumer). Эти события создаются только методами eval и drop; возвращаемые значения этих методов — списки событий, созданных соответствующим вызовом. Поэтому, как и в примере выше, события можно использовать и без подписки на их получение.
Если вы опробуете этот пример, то увидите, что оператор или объявление переменной без завершающей точки с запятой просто не будет выполнено. Незавершённая запись (например, предполагаемый многострочный метод) также не будет выполнена после ввода одной строки. Утилиты в SourceCodeAnalysis предоставляют средства анализа границ исходного кода и его полноты, позволяющие обрабатывать подобные случаи. SourceCodeAnalysis также предлагает варианты дополнения введённых данных, что можно использовать, например, для автодополнения по клавише Tab.
- Начиная с:
- 9
| Класс | Описание |
|---|---|
| DeclarationSnippet | Общий класс для всех фрагментов-объявлений: объявлений переменных ( VarSnippet), объявлений методов (MethodSnippet) и объявлений типов (TypeDeclSnippet). |
| Diag | Диагностическая информация о фрагменте. |
| ErroneousSnippet | Фрагмент кода, который не является допустимым кодом на языке программирования Java. |
| EvalException | Оборачивает исключение, выброшенное выполняемым клиентом. |
| ExpressionSnippet | Фрагмент для присваивания или выражения со значением переменной. |
| ImportSnippet | Фрагмент для объявления импорта. |
| JShell | Механизм состояния вычислений JShell. |
| JShell.Builder | Построитель экземпляров JShell. |
| JShellConsole | Интерфейс, предоставляющий функциональность для Console во фрагменте пользователя. |
| JShellException | Суперкласс исключений, генерируемых JShell. |
| MethodSnippet | Фрагмент для определения метода. |
| PersistentSnippet | Общий класс для фрагментов, которые сохраняются и влияют на последующий код. |
| Snippet | Snippet представляет фрагмент исходного кода Java, передаваемый в JShell.eval(java.lang.String). |
| Snippet.Kind | Описывает общий тип фрагмента. |
| Snippet.Status | Описывает текущее состояние фрагмента. |
| Snippet.SubKind | Описывает конкретную разновидность фрагмента. |
| SnippetEvent | Описание изменения фрагмента. |
| SourceCodeAnalysis | Предоставляет средства анализа входных данных исходного кода. |
| SourceCodeAnalysis.Attribute | Атрибут диапазона, который можно использовать для выбора цвета. |
| SourceCodeAnalysis.Completeness | Описывает полноту заданных входных данных. |
| SourceCodeAnalysis.CompletionInfo | Результат analyzeCompletion(String input). |
| SourceCodeAnalysis.Documentation | Документация для варианта продолжения ввода пользователя. |
| SourceCodeAnalysis.Highlight | Назначает атрибуты для раскрашивания диапазонам внутри фрагмента. |
| SourceCodeAnalysis.QualifiedNames | Список возможных полных имён. |
| SourceCodeAnalysis.SnippetWrapper | Обёртка, преобразующая фрагмент исходного кода Java в допустимый исходный код верхнего уровня Java. |
| SourceCodeAnalysis.Suggestion | Вариант продолжения ввода пользователя. |
| StatementSnippet | Фрагмент для оператора. |
| TypeDeclSnippet | Фрагмент для определения типа (класса, интерфейса, перечисления или аннотационного интерфейса). |
| UnresolvedReferenceException | Исключение, возникающее при попытке выполнить фрагмент RECOVERABLE_DEFINED. |
| VarSnippet | Фрагмент для определения переменной. |
© 1993, 2025, Oracle and/or its affiliates. All rights reserved.
Documentation extracted from Debian's OpenJDK Development Kit package.
Licensed under the GNU General Public License, version 2, with the Classpath Exception.
Various third party code in OpenJDK is licensed under different licenses (see Debian package).
Java and OpenJDK are trademarks or registered trademarks of Oracle and/or its affiliates.
https://docs.oracle.com/en/java/javase/25/docs/api/jdk.jshell/jdk/jshell/package-summary.html