Пакет 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 | Фрагмент представляет собой фрагмент исходного кода Java, передаваемый в JShell.eval(java.lang.String). |
| Snippet.Kind | Описывает общий вид фрагмента. |
| Snippet.Status | Описывает текущее состояние фрагмента. |
| Snippet.SubKind | Описывает конкретную разновидность фрагмента. |
| SnippetEvent | Описание изменения фрагмента. |
| SourceCodeAnalysis | Предоставляет средства анализа исходного кода. |
| SourceCodeAnalysis.Attribute | Атрибут диапазона, который можно использовать для выбора цвета. |
| SourceCodeAnalysis.Completeness | Описывает полноту заданных входных данных. |
| SourceCodeAnalysis.CompletionContext | Различные флаги, описывающие контекст, в котором выполняется автодополнение. |
| SourceCodeAnalysis.CompletionInfo | Результат analyzeCompletion(String input). |
| SourceCodeAnalysis.CompletionState | Предоставляет доступ к состоянию автодополнения. |
| SourceCodeAnalysis.Documentation | Документация для кандидата на продолжение введённых пользователем данных. |
| SourceCodeAnalysis.ElementSuggestion | Описание Element, который может быть продолжением заданного фрагмента. |
| SourceCodeAnalysis.ElementSuggestionConvertor<S> | Преобразователь списка SourceCodeAnalysis.ElementSuggestion в список пользовательских целевых элементов автодополнения. |
| 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.