【问题标题】:Instantiating anonymous inner classes in Java with additional interface implementation使用附加接口实现在 Java 中实例化匿名内部类
【发布时间】:2014-02-02 20:20:39
【问题描述】:

假设我有以下两个类/接口定义:

public abstract class FooClass {
    public abstract void doFoo();
}

public interface BarInterface {
    public void doBar();
}

如果我想创建一个扩展/实现两者的匿名内部类,我需要这样做吗:

public abstract class BothClass extends FooClass implements BarInterface {}

...

new BothClass() {
    public void doFoo() {
        System.out.println("Fooooooooo!!!!");
    }

    public void doBar() {
        System.out.println("Baaaaaaaar!!!!");
    }
}.doBar();

或者有什么捷径可以让我不定义BothClass?可能是这样的:

new (FooClass implements BarInterface)() {
    public void doFoo() {
        System.out.println("Fooooooooo!!!!");
    }

    public void doBar() {
        System.out.println("Baaaaaaaar!!!!");
    }
}.doBar();

(这个想法给了我几个错误,这里没有一个有用)

【问题讨论】:

  • FooClass实现BarInterface?我不确定你的意思。
  • @JoshM:假设我不能/不想让FooClass 实现BarInterface
  • 没有捷径。
  • @MarkusA。匿名类是现有类定义的实现。如果你想要两者,你需要一个在你的第一个例子中定义的类。

标签: java subclassing anonymous-inner-class interface-implementation


【解决方案1】:

Let's go to the JLS:

匿名类声明自动从类派生 Java 编译器的实例创建表达式。

类实例创建表达式在哪里

ClassInstanceCreationExpression:
    new TypeArgumentsopt TypeDeclSpecifier TypeArgumentsOrDiamondopt
                                                            ( ArgumentListopt ) ClassBodyopt
    Primary . new TypeArgumentsopt Identifier TypeArgumentsOrDiamondopt
                                                            ( ArgumentListopt ) ClassBodyopt

TypeArgumentsOrDiamond:
    TypeArguments
    <> 

ArgumentList:
    Expression
    ArgumentList , Expression

所以,不,Java 语言规范不允许使用任何快捷方式来使您的匿名类实现比您子类型化的类型更多的接口。

所以,给determine the type of the anonymous class

如果类实例创建表达式以类体结尾,则 被实例化的类是一个匿名类。那么:

  • 如果 T 表示接口,则 Object 的匿名直接子类 声明了实现由 T 命名的接口。

[...]

  • 令 T 为由标识符和任何类型参数命名的类型。一个 声明了由 T 命名的类的匿名直接子类。这 子类的主体是类实例中给出的 ClassBody 创作表达。

您的替代方案就是这样做的方法。

你也可以使用local classes.

【讨论】:

    【解决方案2】:

    匿名类

    FooClass f = new FooClass() {
      public void doFoo() {}
    };
    

    只是具有生成名称的本地类定义的便捷简写

    class $anon extends FooClass {
      public void doFoo() {}
    }
    FooClass f = new $anon();
    

    如果你想实现接口,只需显式编写本地类定义

    class LocalFoo extends FooClass implements BarInterface {
      // method declarations here
    }
    LocalFoo lf = new LocalFoo();
    

    【讨论】: