Спецификация языка Java - не может понять "BlockStatement"
Я изучил спецификацию языка Java здесь (вместо этого я должен был выпить пива), и мне интересно, что может содержать метод. В спецификации указано, что тело метода может содержать блок
MethodBody:
Block
Где "Блок" содержит "BlockStatements". Правило "BlockStatement" выглядит следующим образом:
BlockStatement :
LocalVariableDeclarationStatement
ClassOrInterfaceDeclaration
[Identifier :] Statement
Я могу понять "LocalVariableDeclarationStatement", который может быть
[final] int x, y, z;
Однако я не получаю , почему существует правило ClassOrInterfaceDeclaration. Это правило выглядит так:
ClassOrInterfaceDeclaration:
ModifiersOpt (ClassDeclaration | InterfaceDeclaration)
ClassDeclaration:
class Identifier [extends Type] [implements TypeList] ClassBody
InterfaceDeclaration:
interface Identifier [extends TypeList] InterfaceBody
Что здесь происходит - вы не можете объявить класс или интерфейс внутри блока, конечно?
Может кто-нибудь помочь разъяснить эту путаницу, пожалуйста?
Обновить. Я могу определить класс внутри метода, но следующее не будет работать:
public class Foo {
public void doFoo() {
interface dooJa {
int bar();
}
}
}
Компилятор жалуется, заявив: "Интерфейс пользователя dooJa может быть определен только внутри класса или интерфейса верхнего уровня"... любые объяснения?
Ответы
Ответ 1
Вы хорошо заметили, что интерфейсы больше не работают. Причина в том, что вы смотрите на очень старую версию грамматики. Он выглядит старше 10 лет. Взгляните на грамматику Java 6 (что вы, вероятно, тестируете):
http://www.it.bton.ac.uk/staff/rnb/bosware/javaSyntax/rulesLinked.html#BlockStatement
Вы увидите blockstatement:
BlockStatement: LocalVariableDeclarationStatement ClassDeclaration Заявление
Ответ 2
О да, вы можете объявить класс внутри тела метода.: -)
class A {
public void doIt() {
class B {}
B b = new B();
System.out.println(b.getClass());
}
}
Ответ 3
Пример для блока с объявлением внутреннего класса:
public class Test {
static
{
class C {}
C c = new C();
}
}
Хотя я сомневаюсь, что вы найдете прецедент...
Ответ 4
Как говорили другие, вы можете объявить класс внутри метода. Одним из вариантов использования этого является использование этого в качестве альтернативы для анонимного внутреннего класса. У анонимных внутренних классов есть некоторые недостатки; например, вы не можете объявить конструктор в анонимном внутреннем классе. С классом, объявленным локально в методе, вы можете.
Вот глупый пример, который на самом деле не показывает, почему вы хотите это сделать, но по крайней мере, как вы могли это сделать.
public Runnable createTask(int a, int b) {
// Method-local class with a constructor
class Task implements Runnable {
private int x, y;
Task(int x, int y) {
this.x = x;
this.y = y;
}
@Override
public void run() {
System.out.println(x + y);
}
}
return new Task(a, b);
}
Ответ 5
Они называются локальными классами. Я использую это время от времени, но это не настоящая необходимость.
Изменить: локальный класс может быть статическим, если он отображается в статическом контексте, например, в статическом методе.
Из формулировки spec, local/inner/anno classe всегда означает только class
, а не interface
.