Search code examples
javalambdajava-8functional-interface

Is there a way to turn an existing interface into a functional interface?


I am using an interface that looks something along the lines of this:

public interface ObjectListener {
    public void objectAdded(Object o);
    public void objectRemoved(Object o);
}

And I am currently using an anonymous class to implement the interface, but I don't care about one of the two methods. Something along the lines of this:

someObject.addListener(new ObjectListener() {

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

    @Override
    public void objectRemoved(Object o) {}
});

Now, I've been using the new lambda expressions in Java 8 wherever I'm able, and I would like to use the added simplicity in a situation like this. After all, I'm only implementing one of the methods, but since there are two methods in the interface, I can't use it in a lambda expression.

Is there a way for me to get around this restriction?


Solution

  • In order to reuse an existing interface that is not a functional interface in a lambda expression, you must also use the new Java8 feature, default methods.

    In this case, if you wanted to use a lambda expression in place of the anonymous class, you would have to do the following.

    First, you need to redefine the ObjectListener as a new interface:

    public interface ObjectAddedListener extends ObjectListener {
        @Override
        default public void objectRemoved(Object o) {}
    }
    

    We just simply add an empty default implementation to the method that we don't care about, which leaves the objectAdded() method as the sole abstract method in the interface.

    Then you can use the new type in place of any ObjectListener, and since there is only one method without an implementation in the new interface, you can use it in lambda expressions, like so:

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

    Note that if you wanted to use this new type directly in the addListener() method you would first need to cast the lambda expression as the newly defined type like so:

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