摘要类的Lambda表达式

时间:2015-12-22 21:05:24

标签: 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
            }
        });
    }
}

3 个答案:

答案 0 :(得分:45)

你不能直接将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.function包中的相应界面,而不是java.util.function.Supplier

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

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

答案 1 :(得分:37)

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

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

As a reference, thats Brian Goetz所说的关于在SAM抽象类上允许lambdas的内容。

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

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

  • 使模型复杂化 几百%使用案例似乎是一个不好的交易

答案 2 :(得分:0)

同时,我们现在在接口中具有默认实现。我处于类似情况,尝试过抽象类。使用两种方法切换到接口,其中一种具有默认实现。 Java将接口标识为具有单个抽象方法,我可以使用lambda语法将接口的实现作为参数传递。

缺点是,如果有人真的坚持,可以通过在某些(匿名或非匿名)类中显式实现接口来覆盖具有默认实现的方法。而且您不能限制它,因为在接口上所有方法都是公共的。根据您的情况,可能没什么大不了的。