Подтвердить что ты не робот

Спецификация языка 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 может быть определен только внутри класса или интерфейса верхнего уровня"... любые объяснения?

4b9b3361

Ответ 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.