Вопрос

Java allows me to define local abstract classes, like in this example:

public class Foo {

    public void foo() {
        abstract class Bar {          // Bar is a local class in foo() ...
            abstract void bar();
        }

        new Bar() {                   // ... and can be anonymously instantiated
            void bar() {
                System.out.println("Bar!");
            }
        }.bar();
    }
}

For some reason, when I try to define a "local interface" instead of the local class, like this:

public class Foo {

    public void foo() {
        interface Bar {           // Bar was supposed to be a local interface...
            void bar();
        }

        new Bar() {               // ... to be anonymously instantiated
            void bar() {
                System.out.println("Bar!");
            }
        }.bar();
    }
}

Java complains that "The member interface Bar can only be defined inside a top-level class or interface". Is there a reason for this? Or am I missing a mistake I made?

Это было полезно?

Решение

There simply isn't a definition for it in the JLS. It just doesn't exist.

As for a weak reason, according to the JLS 14.3:

All local classes are inner classes (§8.1.3).

An interface can't be inner (JLS 8.1.3):

Member interfaces (§8.5) are implicitly static so they are never considered to be inner classes.

So we can't have a local interface.

This is, I guess, in addition to what @SotiriosDelimanolis has found that InterfaceDeclaration is not a BlockStatement.

Другие советы

The Java Language Specification doesn't tell you why it was designed the way it was, but it does describe what is and what isn't allowed.

A method body has the following form

MethodBody:
    Block 
    ;

where Block is

Block:
    { BlockStatementsopt }

BlockStatements:
    BlockStatement
    BlockStatements BlockStatement

BlockStatement:
    LocalVariableDeclarationStatement
    ClassDeclaration
    Statement

So a class declaration is allowed, but an interface isn't.


We can argue that having a local interface is not very useful from a caller point of view. It doesn't serve any purpose. An interface is meant to describe behavior, but since the interface would be local, no caller could make use of it. You could just as well define and implement the behavior in a class.

Local interfaces (and enums) have been introduced along record classes feature:

Unfortunately this feature is a little bit obscured in the documentation - but it works.

Both versions allow to write code like below:

public class Main {

    public int foo() {

        interface Experimentable {
            int bar();
        }

        Experimentable e = new Experimentable() {
            @Override
            public int bar() {
                return 0;
            }
        };

        return e.bar();
    }

    public static void main(String[] args) {
        System.out.println(new Main().foo());
    }

}

Java now (starting from 16) supports local interface.

A local interface is a nested interface (§9 (Interfaces)) whose declaration is immediately contained by a block.

And your (slightly corrected because bar implmentation must be public) code compiles just fine.

public class Foo {

    public void foo() {
        interface Bar {           // Bar was supposed to be a local interface...
            void bar();
        }

        new Bar() {               // ... to be anonymously instantiated
            public void bar() {
                System.out.println("Bar!");
            }
        }.bar();
    }
}

Compilation:

~/tmp $ /usr/local/opt/java/bin/javac -version
javac 17
~/tmp $ /usr/local/opt/java/bin/javac Foo.java
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top