抽象类的 Lambda 表达式

2022-09-01 00:52:53

我有一个抽象类,只有一个抽象方法。如何使用 lambda 表达式来实例化它。它不能成为接口,因为它扩展了一个类。

public class Concrete<T> {
    // Has a bunch of predefined methods.
}


public abstract class Abstract<T> extends Concrete<T> {
    public T getSomething();
    // Uses inherited methods from Concrete class
}

public class Driver {
    public static void main(String[] args) {
        System.out.println(new Abstract<String>() {
            public String getSomething() {
                // Returns something using inherited methods from Abstract              
                // Class and Concrete Class
            }
        });
    }
}

答案 1

你不能直接让 lambda 表达式成为抽象类,正如 Sleiman Jneidi 在他的答案中指出的那样。但是,您可以使用解决方法:

public class AbstractLambda<T> extends Abstract<T>
{
    private final Supplier<? extends T> supplier;
    public AbstractLambda(Supplier<? extends T> supplier)
    {
        this.supplier = supplier;
    }

    @Override
    public T getSomething()
    {
        return this.supplier.get();
    }
}

这可以与 lambda 表达式一起使用:

Abstract<String> a = new AbstractLambda<>(() -> "Hello World");
System.out.println(a.getSomething()); // prints 'Hello World'

如果您的方法具有参数,请使用包中的某个接口或相应的接口,而不是 。getSomething(...)java.util.function.Functionjava.util.functionjava.util.function.Supplier


这也是允许您使用 lambda 而不是必须对类进行子类类化的方式:java.lang.ThreadRunnable

Thread t = new Thread(() -> System.out.println("Hello World"));
t.start();

答案 2

不,你做不到。Lambda 必须在接口上面向单个抽象方法 (SAM),并且它们不能在抽象类上使用单个抽象方法。事情就是这样,你必须接受它,

尽管拥有它们很有意义,但语言设计人员认为,通过在 SAM 抽象类上允许 lambdas 来引入复杂性是值得的。

作为参考,这就是Brian Goetz所说的关于在SAM抽象类上允许lambdas的话。

布莱恩电子邮件中的主要要点:

  • 只有 3% 的 lambda 候选内部类实例将抽象类作为其目标

  • 为了百分之几的用例而使模型复杂化似乎是一个糟糕的交易。


推荐