jshell - не удалось найти printf

Почему мой экземпляр jshell (JDK Version 9-ea) не может идентифицировать оператор printf()? Ниже приведена ошибка, которую я наблюдаю,

jshell> printf("Print number one - %d",1)
|  Error:
|  cannot find symbol
|    symbol:   method printf(java.lang.String,int)
|  printf("Print number one - %d",1)
|  ^----^

Я могу получить доступ к printf, если укажу его обычным способом.

jshell> System.out.printf("Print number one - %d",1)
Print number one - 1$1 ==> java.io.PrintStream@1efbd816

Любые указатели?


person R K    schedule 05.05.2017    source источник


Ответы (4)


В более ранней версии JShell был предопределен метод printf, но он был удален из сборок раннего доступа. Конечно, вы можете определить свой собственный метод printf:

jshell> void printf(String format, Object... args) { System.out.printf(format, args); }

Или вы можете вернуть методы печати, которые были в более ранних сборках, запустив JShell с помощью:

jshell --start DEFAULT --start PRINTING

(Если вы используете только --start PRINTING, вы не получите импорт по умолчанию.)

Для получения дополнительной информации см. ошибку JDK-8172102 в базе данных ошибок Java и наборе изменений. b2e915d476be, который это реализовал.

person David Conrad    schedule 09.05.2017

Он просто работает без jshell? Это не может работать таким образом, так как такой метод не определен вне PrintStream.

Вы можете определить свой собственный printf следующим образом:

jshell> private  void printf(String s) { System.out.println(s); }

И позже используйте его:

jshell> printf("test")
test
person Eugene    schedule 05.05.2017
comment
Раньше он работал внутри JShell. Это тоже не очень хороший printf метод. - person David Conrad; 09.05.2017

Java — это объектно-ориентированный язык, и вы не можете вызывать нестатический метод без объекта, связанного с этим методом. printf — это нестатический метод класса PrintStream, и вы не можете вызвать его без экземпляра PrintStream.

В стандартной библиотеке Java есть несколько экземпляров PrintStream, таких как System.out и System.err, поэтому вы можете вызывать System.out.printf() или System.err.printf(), но обычный printf() не работает, потому что jshell не знает, какому объекту принадлежит этот printf().

person ZhekaKozlov    schedule 05.05.2017
comment
Это верно для Java в целом, но не для JShell. Вы можете определить метод без определения класса, и JShell раньше определял метод printf, хотя он больше не определен по умолчанию. - person David Conrad; 09.05.2017
comment
@DavidConrad Все методы, определенные в jshell, неявно статичны. Вот почему вы можете вызывать их без объектов. - person ZhekaKozlov; 10.05.2017
comment
Речь идет не о том, чтобы вызывать их без объектов, а о том, чтобы определять их без окружающего класса. У вас не может быть метода, даже статического, вне класса в Java. Но, по-видимому, в JShell есть какой-то класс по умолчанию, из которого он делает их методами. - person David Conrad; 10.05.2017
comment
@DavidConrad Да, в jshell есть неявный охватывающий класс. Если вы напишете class A {} в jshell, то A.class.getEnclosingClass() != null вернет true. - person ZhekaKozlov; 10.05.2017

Это может быть удобнее:

jshell> /set start -retain DEFAULT PRINTING

(Необходимо установить это один раз. В следующий раз вы можете просто запустить jshell без каких-либо аргументов). См. официальную документацию jshell. .

person rmuller    schedule 25.09.2017