Spec-Zone.ru › OpenJDK 25

Пакет jdk.jshell

package jdk.jshell
Предоставляет интерфейсы для создания инструментов, таких как цикл чтения-вычисления-вывода (REPL), который интерактивно выполняет «фрагменты» кода на языке программирования Java. «Фрагментом» считается отдельное выражение, оператор или объявление. Эту функциональность можно использовать для расширения таких инструментов, как IDE, или применять автономно.

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
Пакет Описание
jdk.jshell.execution
Предоставляет поддержку реализации для создания механизмов выполнения JShell.
jdk.jshell.spi
Определяет интерфейс поставщика служб для подключаемых механизмов выполнения JShell.
jdk.jshell.tool
Предоставляет механизм для запуска экземпляра инструмента Java shell.
Класс Описание
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
Фрагмент для определения переменной.

Сообщить об ошибке или предложить улучшение
Дополнительную справочную информацию по API и документацию для разработчиков см. в разделе Документация Java SE, где приводятся более подробные описания для разработчиков, концептуальные обзоры, определения терминов, обходные решения и примеры работающего кода. Другие версии.
Java является товарным знаком или зарегистрированным товарным знаком Oracle и/или её аффилированных лиц в США и других странах.
Авторские права © 1993, 2025, Oracle и/или её аффилированные лица, 500 Oracle Parkway, Redwood Shores, CA 94065 USA.
Все права защищены. Использование регулируется условиями лицензии и политикой распространения документации.

© 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

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API