I have seen in many libraries like Spring
which use a lot of interfaces with single methods in them like BeanNameAware
, etc.
With Java 8, keeping the single method interface is quite useful, since single method interfaces will allow the usage of closures and "function pointers". So, whenever your code is written against a single method interface, the client code may hand in a closure or a method (which must have a compatible signature to the method declared in the single method interface) instead of having to create an anonymous class. In contrast, if you make one interface with more than one method, the client code will not have that possibility. It must always use a class that implements all methods of the interface.
So as a common guideline, one can say: If a class that only exposes a single method to the client code might be useful to some client, then using a single method interface for that method is a good idea. A counter example to this is the Iterator
interface: Here, it would not be useful having only a next()
method without a hasNext()
method. Since having a class that only implements one of these methods is no use, splitting this interface is not a good idea here.
Example:
interface SingleMethod{ //The single method interface
void foo(int i);
}
class X implements SingleMethod { //A class implementing it (and probably other ones)
void foo(int i){...}
}
class Y { //An unrelated class that has methods with matching signature
void bar(int i){...}
static void bar2(int i){...}
}
class Framework{ // A framework that uses the interface
//Takes a single method object and does something with it
//(probably invoking the method)
void consume(SingleMethod m){...}
}
class Client{ //Client code that uses the framework
Framework f = ...;
X x = new X();
Y y = new Y();
f.consume(x); //Fine, also in Java 7
//Java 8
//ALL these calls are only possible since SingleMethod has only ONE method!
f.consume(y::bar); //Simply hand in a method. Object y is bound implicitly
f.consume(Y::bar2); //Static methods are fine, too
f.consume(i -> { System.out.println(i); }) //lambda expression. Super concise.
//This is the only way if the interface has MORE THAN ONE method:
//Calling Y.bar2 Without that closure stuff (super verbose)
f.consume(new SingleMethod(){
@Override void foo(int i){ Y.bar2(i); }
});
}