抽象类的Lambda表达式

Hal*_*ort 34 java lambda

我有一个抽象类,有一个抽象方法.我如何使用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
            }
        });
    }
}
Run Code Online (Sandbox Code Playgroud)

Cla*_*oft 46

正如Sleiman Jneidi在他的回答中指出的那样,你不能直接使lambda表达式成为一个抽象类.但是,您可以使用变通方法:

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();
    }
}
Run Code Online (Sandbox Code Playgroud)

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

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

如果您的getSomething(...)方法有参数,请使用包中java.util.function.Function的适当接口java.util.function而不是java.util.function.Supplier.


这也是java.lang.Thread允许你使用Runnablelambda而不是必须子类的方法:

Thread t = new Thread(() -> System.out.println("Hello World"));
t.start();
Run Code Online (Sandbox Code Playgroud)

  • 我不同意 Thread 以类似的方式定义。一个 Runnable 作为 Thread 的构造函数参数是很自然的,Runnable 是简单的 FunctionalInterface。它看起来与此解决方法不同。 (2认同)
  • @snap他们是相似的。唯一的区别是Thread不是抽象的,但它是相同的模式:扩展Thread并重写run()或将Runnable传递给Thread构造函数。 (2认同)

Sle*_*idi 38

不,你不能这样做.Lambdas必须在接口上定位单个抽象方法,并且它们不能在抽象类上使用单个抽象方法.这是怎么回事,你必须接受它,

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

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

Brian的电子邮件的主要关键点:

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

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