Java 有没有办法将现有接口转换为功能接口?

Java 有没有办法将现有接口转换为功能接口?,java,lambda,java-8,functional-interface,Java,Lambda,Java 8,Functional Interface,我使用的界面看起来像这样: public interface ObjectListener { public void objectAdded(Object o); public void objectRemoved(Object o); } someObject.addListener(new ObjectListener() { @Override public void objectAdded(Object o) { doSomethin

我使用的界面看起来像这样:

public interface ObjectListener {
    public void objectAdded(Object o);
    public void objectRemoved(Object o);
}
someObject.addListener(new ObjectListener() {

    @Override
    public void objectAdded(Object o) {
        doSomething(o);
    }

    @Override
    public void objectRemoved(Object o) {}
});
我目前正在使用一个匿名类来实现接口,但我不关心这两种方法中的一种。大致如下:

public interface ObjectListener {
    public void objectAdded(Object o);
    public void objectRemoved(Object o);
}
someObject.addListener(new ObjectListener() {

    @Override
    public void objectAdded(Object o) {
        doSomething(o);
    }

    @Override
    public void objectRemoved(Object o) {}
});
现在,我一直在尽可能地使用Java8中新的lambda表达式,我希望在这种情况下使用增加的简单性。毕竟,我只实现了其中一个方法,但是由于接口中有两个方法,所以我不能在lambda表达式中使用它


我有没有办法绕过这个限制?

为了重用lambda表达式中不是函数接口的现有接口,还必须使用新的Java8特性default methods

在本例中,如果希望使用lambda表达式代替匿名类,则必须执行以下操作

首先,您需要将ObjectListener重新定义为一个新接口:

public interface ObjectAddedListener extends ObjectListener {
    @Override
    default public void objectRemoved(Object o) {}
}
我们只是简单地将一个空的默认实现添加到我们不关心的方法中,这使得
objectAdded()
方法成为接口中唯一的抽象方法

然后,您可以使用新类型代替任何ObjectListener,因为在新接口中只有一个方法没有实现,所以您可以在lambda表达式中使用它,如下所示:

ObjectAddedListener listener = o -> doSomething(o);
someObject.addListener(listener);
请注意,如果要在
addListener()
方法中直接使用此新类型,首先需要将lambda表达式转换为新定义的类型,如下所示:

someObject.addListener((ObjectAddedListener) o -> doSomething(o));

重构不是单一抽象方法(SAM)接口的现有接口以支持与Java8Lambda表达式一起使用的另一种方法是将方法分离为它们自己的类型。如果接口中的大多数方法都适合与lambdas一起使用,那么这是最合适的

例如,考虑一个接口,该接口允许以字段名编程访问数据模型对象。该接口包含一个用于读取字段的方法和另一个用于更改字段的方法:

interface Accessible {
    Object acc(String fieldName);
    void mut(String fieldName, Object val);
}
这两种方法似乎都有可能(甚至有可能)与lambdas一起使用,以获得更好的表达性和简单性。为了实现这一点,可以通过这种方式重构接口(举个例子;有几种方法可以做到这一点):


提供对数据模型对象的读写访问的类现在需要同时实现
Accessors.Accessor
Accessors.Mutator
。不过,重要的是,这些接口(现在都是函数接口)可以用作在代码中使用Java 8 lambda表达式的策略。

请参阅…+1以了解精心编制的问题。或者,如果您可以编辑
ObjectListener
代码,您可以简单地将
{}
添加为
objectRemoved()的主体
即:)无需继承和类型转换。在这种情况下,
ObjectListener
不是我的代码,因此需要扩展接口。此解决方案仅适用于内部代码,这些代码永远不会成为导出的公共API的一部分,并且将由相同的程序员维护。原因是接口中的默认方法不会在尝试实现接口但未实现所有方法的客户端代码中导致编译时错误。对于客户端将要访问的代码,最好将这些方法分离到它们自己的接口定义中。