通过 lambda 表达式实现具有两个抽象方法的接口
Posted
技术标签:
【中文标题】通过 lambda 表达式实现具有两个抽象方法的接口【英文标题】:Implementing an interface with two abstract methods by a lambda expression 【发布时间】:2016-07-14 00:12:21 【问题描述】:在 Java 8 中引入了 lambda 表达式 来帮助减少样板代码。如果接口只有一种方法,它可以正常工作。如果它由多个方法组成,那么这些方法都不起作用。如何处理多种方法?
我们可以参考下面的例子
public interface I1()
void show1();
void show2();
那么主函数的结构会是什么来定义主函数本身的方法呢?
【问题讨论】:
你说的是functional interfaces
吗?将所有其他方法设为default
如果我们不设置任何访问说明符,不应该是默认的吗?
接口方法是自动公开的。如果你不将它们设为默认,它们就不是默认的,而是抽象的。
@SoumyaKantiNaskar,默认情况下,接口方法有public abstract
修饰符。 default
表示方法必须实现
我至少会链接到这个:***.com/questions/25299653/…(可能会认为它是重复的,但我不确定......)
【参考方案1】:
如 Eran 所说,Lambda 表达式仅可用于功能接口,但如果您确实需要接口中的多个方法,您可以将修饰符更改为 default
或 static
并在必要时在实现它们的类中覆盖它们.
public class Test
public static void main(String[] args)
I1 i1 = () -> System.out.println(); // NOT LEGAL
I2 i2 = () -> System.out.println(); // TOTALLY LEGAL
I3 i3 = () -> System.out.println(); // TOTALLY LEGAL
interface I1
void show1();
void show2();
interface I2
void show1();
default void show2()
interface I3
void show1();
static void show2 ()
继承
你不应该忘记继承的方法。
这里I2
继承了show1
和show2
,因此不能作为函数接口。
public class Test
public static void main(String[] args)
I1 i1 = () -> System.out.println(); // NOT LEGAL BUT WE SAW IT EARLIER
I2 i2 = () -> System.out.println(); // NOT LEGAL
interface I1
void show1();
void show2();
interface I2 extends I1
void show3();
注释
为了确保你的接口是函数式接口,你可以添加如下注解@FunctionalInterface
@FunctionalInterface <------- COMPILATION ERROR : Invalid '@FunctionalInterface' annotation; I1 is not a functional interface
interface I1
void show1();
void show2();
@FunctionalInterface
interface I2
void show3();
【讨论】:
注意I2
可以扩展I1
+1
@PeterLawrey 谢谢,我加了一点解释 Peter :)
您的继承示例也不会为 i
编译。
@eis 谢谢。已编辑。【参考方案2】:
Lambda 表达式只能用于实现函数式接口,即具有单个抽象方法的接口。具有两个抽象方法的接口不能由 lambda 表达式实现。
【讨论】:
您还必须将@FunctionalInterface 注解添加到接口(@987654321@),编译器会检查接口中是否只有一个方法。 那么有没有其他替代方法可以像在 Lambda 表达式中一样删除样板代码? @MartinKrüger 您可以添加该注释,但您不必这样做。编译器会将满足函数式接口定义的任何接口视为函数式接口,无论接口声明中是否存在 FunctionalInterface 注释 @MartinKrüger 您没有有添加@FunctionalInterface
注释来将接口用作lambda。虽然它有助于作为一个标记来表明这将只有一个抽象方法。
@SoumyaKantiNaskar 除非您为界面中的所有方法提供默认实现,但其中一个除外。【参考方案3】:
我一般是直接在接口中创建静态工厂方法:
public inteface I1
void show1();
void show2();
public static I1 of(Runnable show1, Runnable show2)
return new I1()
void show1() show1.run();
void show2() show2.run();
;
用法:
I1 i1 = I1.of(() -> System.out.println("show1"), () -> System.out.println("show2"));
【讨论】:
为什么是静态工厂而不是构造函数? @Nikolas interface 的构造函数? 用于接口实现。【参考方案4】:你总是可以使用合成:
public inteface I1
void show1();
void show2();
public class I1Adapter
private final Runnable r1,r2;
public I1Adapter(Runnable r1, Runnable r2) this.r1=r1; this.r2=r2;
public void show1() r1.run();
public void show2() r2.run();
public static I1Adapter compose(Runnable r1, Runnable r2)
return new I1Adapter(r1,r2);
不可以(使用静态导入):
I1 i1 = compose(()->foo(), ()->bar());
【讨论】:
以上是关于通过 lambda 表达式实现具有两个抽象方法的接口的主要内容,如果未能解决你的问题,请参考以下文章
为什么Comparator接口有两个抽象方法compare和equals,却可以用Lambda