Should 'Comparable<T>' be a 'Functional interface'?
A lambda expression can be used where an instance of an interface with a single abstract method is required. You wrote,
Simply because an interface happens to have single abstract method, it should not be considered as a functional interface.
This is exactly correct. Having a single abstract method is a structural property of an interface, one that makes it eligible to be implemented with a lambda. However, whether an interface makes sense or is semantically sensible to be implemented with lambda is a different story. The latter is the purpose of the @FunctionalInterface
annotation. When it is present on an interface, it indicates the intent that the interface is useful to be implemented with a lambda.
Notably, the Comparable
interface lacks the @FunctionalInterface
annotation.
While it's probably nonsensical to use a lambda as a Comparable
implementation, there doesn't seem to be any reason to create a mechanism to prevent this from being done. It doesn't seem like doing this would be a source of error, which would be a good reason to develop such a mechanism. By contrast, the @FunctionalInterface
annotation is intended to guide programmers in the right direction instead of prohibiting something that is arguably wrong but doesn't seem truly harmful.
The issue comes from a subtle difference between a "method" and a "function".
The output value of a function depends ONLY on the arguments that are input to that function.
However the output of a method depends on the arguments that are input to the function but it may also depend on the object's state (instance variables).
That is, any function is a method but not all methods are functions.
For example, the method compare in the interface Comparator depends only on its arguments. However, the method compareTo in the interface Comparable depends on the state of the object to compare to, so it needs to be implemented in a class.
So even Comparable has one abstarct method, semantically it shouldn't be considered as a functional interface.
Well, asides from the discussion how usefull the informative annotation @FunctionalInterface
is (and I am happy Java 8 does not require it for lambdas).
Comparable
is typically a property of a type and therefore not a good candidate for a functional interface. It is explicitly described as the natural ordering and does not take the two this/that arguments. So this property makes it unlikely any method would operate on a lambda (similliar argument is applicable for nearly all -able
interfaces).
So, the collection designers use a second interface for that task: Comparator<T>
, and for that a lambda implementing it is a very natural choice.