Java语言规范-无法理解';区块语句';

Java语言规范-无法理解';区块语句';,java,language-features,Java,Language Features,我一直在研究Java语言规范(相反,我应该出去喝杯啤酒),我很好奇一个方法可以包含什么。规范规定方法体可以包含块 MethodBody: Block 其中“块”包含“块语句”。“BlockStatement”规则如下所示: BlockStatement : LocalVariableDeclarationStatement ClassOrInterfaceDeclaration [Identifier :] Statement 我能理解“LocalVaria

我一直在研究Java语言规范(相反,我应该出去喝杯啤酒),我很好奇一个方法可以包含什么。规范规定方法体可以包含块

MethodBody:
    Block
其中“块”包含“块语句”。“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只能在顶级类或接口中定义”。。。有什么解释吗?

哦,是的,您可以在方法体中声明一个类。:-)


具有内部类声明的块的示例:

public class Test {

    static 
    {
        class C {}
        C c = new C();
    }
}
尽管我怀疑您是否会找到一个用例…

正如其他人所说,您可以在方法中声明一个类。这种情况的一个用例是将其用作匿名内部类的替代方案。匿名内部类有一些缺点;例如,不能在匿名内部类中声明构造函数。使用在方法中本地声明的类,您可以

这里有一个愚蠢的例子,它并没有真正说明为什么你想这样做,但至少你可以这样做

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);
}

您已经很好地观察到接口不再工作。原因是你看到的是一个非常古老的语法版本。它看起来已经超过10年了。看看Java 6的语法(您可能正在使用它进行测试):

您将看到blockstatement:

区块声明: LocalVariableDeclarationStatement 类声明 声明


这些被称为本地类。我偶尔会用它,但这不是必要的

编辑:局部类可以是静态的,如果它出现在静态上下文中,例如在静态方法中


从规范的措辞来看,local/internal/anno classe始终仅表示
,而不是
接口

好吧,我会。。。我在想什么匿名的内部阶级之类的。谢谢你。顺便说一句,我认为我在Eclipse中尝试这一点是积极主动的。但是,当我使用“public”标识符时,它给了我一个错误,这是不允许的(只有抽象或最终的),但我得到了错误,并假设(未经检查)您无法在方法中定义类或接口。但是,在方法中定义接口对我来说不起作用。在Eclipse中,我得到一个错误:“成员接口dooJa只能在顶级类或接口中定义”。但是,定义一个类确实有效。好吧,您可以始终使用匿名内部类在封闭方法中创建接口的实例,不是吗?但是您将无法返回它(除非您计划返回一个对象),因为外部世界不知道该接口。另外,强制执行方法范围内的契约有什么意义?:)是的,但这似乎不适用于接口,即使语言规范说你也可以定义接口。那就更好了!谢谢你。现在,啤酒在哪里:-)没问题。更准确地说,这里的页面描述了语言规范的不同添加:
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);
}