匿名类的多重继承

102

匿名类如何实现两个(或多个)接口?或者说,它如何既扩展一个类又实现一个接口?例如,我想创建一个匿名类的对象,它同时扩展了两个接口:

    // Java 10 "var" is used since I don't know how to specify its type
    var lazilyInitializedFileNameSupplier = (new Supplier<String> implements AutoCloseable)() {
        private String generatedFileName;
        @Override
        public String get() { // Generate file only once
            if (generatedFileName == null) {
              generatedFileName = generateFile();
            }
            return generatedFileName;
        }
        @Override
        public void close() throws Exception { // Clean up
            if (generatedFileName != null) {
              // Delete the file if it was generated
              generatedFileName = null;
            }
        }
    };

然后我可以将其作为AutoCloseable懒初始化实用程序类,在try-with-resources块中使用:

        try (lazilyInitializedFileNameSupplier) {
            // Some complex logic that might or might not 
            // invoke the code that creates the file
            if (checkIfNeedToProcessFile()) {
                doSomething(lazilyInitializedFileNameSupplier.get());
            }
            if (checkIfStillNeedFile()) {
                doSomethingElse(lazilyInitializedFileNameSupplier.get());
            }
        } 
        // By now we are sure that even if the file was generated, it doesn't exist anymore

我不想创建内部类,因为我绝对确定这个类除了我需要使用的方法之外不会在任何地方使用(而且我可能还想使用在该方法中声明的局部变量,这些变量可能是var类型)。


不幸的是,您必须在其他情况下使构造函数可见。 - Sridhar Sarnobat
6个回答

104

匿名类必须像其他Java类一样扩展或实现某些东西,即使只是java.lang.Object

例如:

Runnable r = new Runnable() {
   public void run() { ... }
};

这里,r 是一个实现了 Runnable 接口的匿名类对象。

使用同样的语法,匿名类也可以扩展另一个类:

SomeClass x = new SomeClass() {
   ...
};

你无法实现多个接口,必须使用命名类才行。然而,匿名内部类和命名类都不能继承超过一个类。


1
我认为第二个表达式不正确。你已经将类的名称声明为SomeClass,它不再是匿名的了。请查看此链接http://docstore.mik.ua/orelly/java-ent/jnut/ch03_12.htm 当你“new”一个接口时,会创建一个匿名类来扩展“Object”类并实现该接口。但是当你使用你写的第一个表达式“new”一个类时,将创建一个匿名类(实际上是该匿名类的实例),该匿名类通过扩展该类来创建。 - lixiang
8
第二个表达式将创建一个继承自SomeClass的匿名类的实例。由于使用了{...},它仍然是匿名的。 - skaffman
1
我明白了,我忽略了{...}。 - lixiang

37

匿名类通常实现一个接口:

new Runnable() { // implements Runnable!
   public void run() {}
}

JFrame.addWindowListener( new WindowAdapter() { // extends  class
} );

如果你的意思是是否可以实现两个或多个接口,那我认为这是不可能的。你可以创建一个私有接口来组合这两个接口。虽然我无法想象为什么你想让一个匿名类具有这种能力:

 public class MyClass {
   private interface MyInterface extends Runnable, WindowListener { 
   }

   Runnable r = new MyInterface() {
    // your anonymous class which implements 2 interaces
   }

 }

我喜欢这个答案,因为它对于寻找在匿名实现中实现2个或更多接口的人来说是友好的。 - L. Holanda

28

我猜没有人理解这个问题。我猜这个家伙想要的是像这样的东西:

return new (class implements MyInterface {
    @Override
    public void myInterfaceMethod() { /*do something*/ }
});

因为这将允许诸如多个接口实现之类的事情:

return new (class implements MyInterface, AnotherInterface {
    @Override
    public void myInterfaceMethod() { /*do something*/ }

    @Override
    public void anotherInterfaceMethod() { /*do something*/ }
});

这确实非常好; 但是在Java中不允许这样做

可以使用方法块内的局部类:

public AnotherInterface createAnotherInterface() {
    class LocalClass implements MyInterface, AnotherInterface {
        @Override
        public void myInterfaceMethod() { /*do something*/ }

        @Override
        public void anotherInterfaceMethod() { /*do something*/ }
    }
    return new LocalClass();
}

准确地说,这是我认为原帖作者的意图。 - DanielCuadra
1
给出一个赞,以回答所提出的问题。在SO上这是很正常的,人们喜欢回答应该被问到的问题,而不是已经被问到的问题。 - mfaisalhyder

16

匿名类 总是 扩展超类或实现接口。例如:

button.addActionListener(new ActionListener(){ // ActionListener is an interface
    public void actionPerformed(ActionEvent e){
    }
});

此外,尽管匿名类无法实现多个接口,但您可以创建一个扩展其他接口的接口,并让您的匿名类实现它。


3
// The interface
interface Blah {
    void something();
}

...

// Something that expects an object implementing that interface
void chewOnIt(Blah b) {
    b.something();
}

...

// Let's provide an object of an anonymous class
chewOnIt(
    new Blah() {
        @Override
        void something() { System.out.println("Anonymous something!"); }
    }
);

1

匿名类在创建对象时进行扩展或实现。例如:

Interface in = new InterFace()
{

..............

}

这里的匿名类正在实现接口。

Class cl = new Class(){

.................

}

这里是一个匿名类继承了一个抽象类。


我看不出有什么区别。你的和我的有什么不同? - trapedInBatcaveWithBAtman
一个不错而且紧凑的答案,我在你的回答中所缺少的是"总是"或"必须"这样的词语 :) - kiedysktos

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接