Recently I started exploring Java 8 and I can't quite understand the concept of "functional interface" that is essential to Java's implementation of lambda expressions. There is a pretty comprehensive guide to lambda functions in Java, but I got stuck on the chapter that gives definition to the concept of functional interfaces. The definition reads:
More precisely, a functional interface is defined as any interface that has exactly one abstract method.
An then he proceeds to examples, one of which is Comparator interface:
public interface Comparator<T> {
int compare(T o1, T o2);
boolean equals(Object obj);
}
I was able to test that I can use a lambda function in place of Comparator argument and it works(i.e. Collections.sort(list, (a, b) -> a-b)).
But in the Comparator interface both compare and equals methods are abstract, which means it has two abstract methods. So how can this be working, if the definition requires an interface to have exactly one abstract method? What am I missing here?
From the same page you linked to:
The interface Comparator is functional because although it declares two abstract methods, one of these—equals— has a signature corresponding to a public method in Object. Interfaces always declare abstract methods corresponding to the public methods of Object, but they usually do so implicitly. Whether implicitly or explicitly declared, such methods are excluded from the count.
I can't really say it better.
Another explanation is given in the #FunctionalInterface page:
Conceptually, a functional interface has exactly one abstract method. Since default methods have an implementation, they are not abstract. If an interface declares an abstract method overriding one of the public methods of java.lang.Object, that also does not count toward the interface's abstract method count since any implementation of the interface will have an implementation from java.lang.Object or elsewhere.
You can test which interface is a correct functional interface using #FunctionalInterface.
E.g.:
this works
#FunctionalInterface
public interface FunctionalInterf {
void m();
boolean equals(Object o);
}
this generates an error:
#FunctionalInterface
public interface FunctionalInterf {
void m();
boolean equals();
}
Multiple non-overriding abstract methods found in interface FunctionalInterf
Q. But in the Comparator interface both compare() and equals() methods are abstract, which means it has two abstract methods. So how can this be working, if the definition requires an interface to have exactly one abstract method? What am I missing here?
A.
A functional interface may specify any public method defined by Object, such as equals( ),
without affecting its “functional interface” status. The public Object methods are considered implicit
members of a functional interface because they are automatically implemented by an instance of a
functional interface.
An interface cannot extend Object class, because Interface has to have public and abstract methods.
For every public method in the Object class, there is an implicit public and abstract method in an interface.
This is the standard Java Language Specification which states like this,
“If an interface has no direct super interfaces, then the interface implicitly declares a public abstract member method m with signature s, return type r, and throws clause t corresponding to each public instance method m with signature s, return type r, and throws clause t declared in Object, unless a method with the same signature, same return type, and a compatible throws clause is explicitly declared by the interface.”
That's how Object class' methods are declared in an interface. And according to JLS, this does not count as interface' abstract method. Hence, Comparator interface is a functional interface.
A functional interface has only one abstract method but it can have multiple default and static methods.
Since default methods are not abstract you’re free to add default methods to your functional interface as many as you like.
#FunctionalInterface
public interface MyFuctionalInterface
{
public void perform();
default void perform1(){
//Method body
}
default void perform2(){
//Method body
}
}
If an interface declares an abstract method overriding one of the public methods of java.lang.Object, that also does not count toward the interface’s abstract method count since any implementation of the interface will have an implementation from java.lang.Object or elsewhere.
Comparator is a functional interface even though it declared two abstract methods. Because one of these abstract methods “equals()” which has signature equal to public method in Object class.
e.g. Below interface is a valid functional interface.
#FunctionalInterface
public interface MyFuctionalInterface
{
public void perform();
#Override
public String toString(); //Overridden from Object class
#Override
public boolean equals(Object obj); //Overridden from Object class
}
Here is a "show me the code" approach to understanding the definition:
we shall look into OpenJDK javac for how it checks validity of classes annotated with #FunctionalInterface.
The most recent (as of July, 2022) implementation lies here:
com/sun/tools/javac/code/Types.java#L735-L791:
/**
* Compute the function descriptor associated with a given functional interface
*/
public FunctionDescriptor findDescriptorInternal(TypeSymbol origin,
CompoundScope membersCache) throws FunctionDescriptorLookupError {
// ...
}
Class Restriction
if (!origin.isInterface() || (origin.flags() & ANNOTATION) != 0 || origin.isSealed()) {
//t must be an interface
throw failure("not.a.functional.intf", origin);
}
Pretty simple: the class must be an interface and must not be a sealed one.
Member Restriction
for (Symbol sym : membersCache.getSymbols(new DescriptorFilter(origin))) { /* ... */ }
In this loop, javac goes through the members of the origin class, using a DescriptorFilter to retrieve:
Method members (of course)
&& that are abstract but not default,
&& and do not overwrite methods from Object,
&& with their top level declaration not a default one.
If there is only one method matching all the above conditions, then surely it is a valid functional interface, and any lambda will overwrite that very method.
However, if there are multiple, javac tries to merge them:
If those methods all share the same name, related by override equivalence:
then we filter them into a abstracts collection:
if (!abstracts.stream().filter(msym -> msym.owner.isSubClass(sym.enclClass(), Types.this))
.map(msym -> memberType(origin.type, msym))
.anyMatch(abstractMType -> isSubSignature(abstractMType, mtype))) {
abstracts.append(sym);
}
Methods are filtered out if:
their enclosing class is super class of that of another previously matched method,
and the signature of that previously matched method is subsignature of that of this method.
Otherwise, the functional interface is not valid.
Having collected abstracts, javac then goes to mergeDescriptors, which uses mergeAbstracts, which I will just quote from its comments:
/**
* Merge multiple abstract methods. The preferred method is a method that is a subsignature
* of all the other signatures and whose return type is more specific {#see MostSpecificReturnCheck}.
* The resulting preferred method has a thrown clause that is the intersection of the merged
* methods' clauses.
*/
public Optional<Symbol> mergeAbstracts(List<Symbol> ambiguousInOrder, Type site, boolean sigCheck) {
// ...
}
Conclusion
Functional interfaces must be interfaces :P , and must not be sealed or annotations.
Methods are searched in the whole inheritance tree.
Methods overlapping with those from Object are ignored.
default methods are ignored, unless they are later overridden by sub-interfaces as non-default.
Matching methods must all share the same name, related by override equivalence.
Either there is only one method matching the above conditions, or matching methods can get "merged" by their class hierarchy, subsignature relations, return types and thrown clauses.
The Java docs say:
Note that it is always safe not to override Object.equals(Object).
However, overriding this method may, in some cases, improve
performance by allowing programs to determine that two distinct
comparators impose the same order.
Maybe Comparator is special? Maybe, even though it's an interface, there is somehow a default implementation of equals() that calls compare()? Algorithmically, it's trivial.
I thought all methods that were declared in interfaces were abstract (i. e. no default implementation). But maybe I'm missing something.
Definition:
If an interface contains only one abstract method, then such type of interface is called functional interface.
Usage:
Once we write Lambda expression "->" to invoke its functionality ,
then in this context we require Functional Interface.
We can use the Functional Interface reference to refer Lambda
expression.
Inside functional interface we can have one abstract method and n
number of default/static methods.
Functional interface with respect to inheritance:
If an interface extends Functional interface and the child interface does not contain any abstract method , then the child interface is also considered to be Functional Interface.
Functional interface is not new to java, its already used in following interface API's:
Runnable : contains run() method only.
Callable : contains call() method only.
Comparable : contains compareTo() method only.
Before Java 8, an interface could only declare one or more methods also known as Abstract Method (method with no implementation, just the signature). Starting with Java 8 an interface can also have implementation of one or more methods (knows as Interface Default Method) and static methods along with abstract methods. Interface Default Methods are marked default keyword.
So the question is, what is Functional Interface?
An interface with Single Abstract Method (SAM) is called Functional Interface.
Which means -
An interface with Single Abstract Method is a Functional Interface
An interface with Single Abstract Method and zero or more default
methods and zero or more static method is also a valid Functional
Interface.
More detail with example code https://readtorakesh.com/functional-interface-java8/
Related
This question already has answers here:
Are all methods of interface abstract?
(7 answers)
Why Functional Interfaces in Java 8 have one Abstract Method?
(4 answers)
what is a abstract method on a interface in java [duplicate]
(4 answers)
When we add two abstract methods in an interface and implement just one method then why can't we implement the other method using lambda?
(1 answer)
Closed 1 year ago.
This post was edited and submitted for review 1 year ago and failed to reopen the post:
Duplicate This question has been answered, is not unique, and doesn’t differentiate itself from another question.
Is the purpose of abstract keyword in a FunctionalInterface to distinguish the 'lambda' method from other abstract methods?
Since methods that have no body in an interface are abstract, and Functional Interfaces that have only one method do not have the abstract keyword, I was wondering whether the real purpose of the abstract keyword is to mark or distinguish which among the 'abstract' methods in a Functional Interface will serve as the 'carrier' of the lambda expression.
Is my understanding correct?
This method does not have the abstract keyword but is a functional interface:
public interface AllTrades {
public boolean checkSalary(ATrade t);
}
now suppose the interface above had 2 methods, they are both abstract,
but the interface is no longer a FunctionalInterface
public interface AllTrades {
public boolean checkSalary(ATrade t);
public boolean checkSalary2(ATrade t);
}
Now if we mark which method is abstract, it is a Functional Interface again:
public interface AllTrades {
abstract public boolean checkSalary(ATrade t);
public boolean checkSalary2(ATrade t);
}
Is my understanding correct?
Although you can use abstract in an interface, it has no extra meaning, as all methods in an interface (except default, private or static methods) are by definition abstract. It has no extra meaning in a functional interface, and if you annotate your interface with #FunctionalInterface, both of your examples with two methods will fail to compile as they are equivalent.
To be complete, your first example does have an abstract method, and is a potential function interface. Your second and third example both have two abstract methods, and cannot be used as a function interface.
See also the Java Language Specification 17, section 9.4:
An interface method lacking a private, default, or static
modifier is implicitly abstract. Its body is represented by a
semicolon, not a block. It is permitted, but discouraged as a matter
of style, to redundantly specify the abstract modifier for such a
method declaration.
(emphasis mine)
and section 9.8:
A functional interface is an interface that is not declared sealed
and has just one abstract method (aside from the methods of
Object), and thus represents a single function contract.
All methods in interfaces are public and abstract by default, and the inclusion of either of those modifiers does not change the behavior of the code in any way. You can verify this by compiling the second and third code samples with the #FunctionalInterface annotation, which would result in a compile time error.
Edit:
From the Java Language Specification
9.8. Functional Interfaces
9.4.3. Interface Method Body
9.6.4.9. #FunctionalInterface
Is the show() method in class B 'overridden', 'implemented' or simply 'defined'?
interface A
{
void show();
}
class B implements A
{
public void show()
{
System.out.println("What is the proper term to explain?");
}
}
A short answer, we override those methods, why?
Because this represents the concept of polymorphic statement, Remember
List<String> aa = new ArrayList<>();
// List => interface
// ArrayList => class
aa.add("polymorphic statment");
Polymorphic statement and overiding go hand in hand.
Although any class also has the option to implement an interface by declaring itself abstract and no need to override any method.
Note: Apply the same concept in any IDE, will guide you to add #Override annotation.
Generally speaking I say "override" to mean redefining an inherited behavior and I keep "implement" to mean defining a behavior (not implemented yet).
So I would say that B implements show().
And the JLS seems to go in this way :
If a non-abstract method mC overrides an abstract method mA from a
class C, then mC is said to implement mA from C.
The oracle example documentation seems to says that override is to redefine a behavior too :
The ability of a subclass to override a method allows a class to
inherit from a superclass whose behavior is "close enough" and then to
modify behavior as needed. The overriding method has the same name,
number and type of parameters, and return type as the method that it
overrides. An overriding method can also return a subtype of the type
returned by the overridden method. This subtype is called a covariant
return type.
Note that the java.lang.Override annotation doesn't say the contrary (emphasis is mine) :
Indicates that a method declaration is intended to override a method
declaration in a supertype. If a method is annotated with this
annotation type compilers are required to generate an error message
unless at least one of the following conditions hold:
The method does override or implement a method declared in a
supertype.
The method has a signature that is override-equivalent to that of any
public method declared in Object.
The API could have provided #Implement additionally to the #Override annotation.
But it seems rather clumsy to have both. So they probably kept a single one : #Override to convey the two things.
The method show() in class B implements the method declared in interface A.
You should say implement because override means that you are overwriting some existing method which is not true in case of interfaces. Interfaces cannot contain method definitions, they merely specify a contract.
Today, I'm trying to learn some features in Java 8, specific about Lambda Expressions. I create a new Comaparator like this :
Comparator<String> strCom = new Comparator<String>() {
#Override
public int compare(String o1, String o2) {
return 0;
}
};
When I read code inside Comparator interface, I have got confused. Althrough interface Comparator have two method compare() and equals(), we don't need implement all of them. I had found some reason why we don't need implement method equals() here. But i also read in javadocs
If your class claims to implement an interface, all methods defined by that interface must appear in its source code before the class will successfully compile. What Is an Interface?
So, can someone help me understand this ? Do not override equals() is still legal ?
equal is not needed to implement because it is inherited from the Object class, as everything in Java is an Object
As you can see in the documentation the equal Method is already defined in the Object class:
https://docs.oracle.com/javase/7/docs/api/java/lang/Object.html
You only need to implement the equals method if you want to check if two Comparators have the same data and therefore are "equal", but this is probably not what are you looking for, as Comparators normally do not hold any instance variables
The tutorial is trying to introduce the concept of interfaces through a simple example, but it ends up being misleading.
Take this code for example:
public interface MyInterface {
public void foo();
public void bar();
}
public class Super {
public void foo() { System.out.println("foo"); }
}
public class Sub extends Super implements MyInterface {
public void bar() { System.out.println("bar"); }
}
This is perfectly valid code, despite the fact that Sub only explicitly implements one of MyInterfaces methods. It's easy to see why this is valid: foo() is already implemented by Super, and that implementation is inherited by Sub.
The exact rule goes like this:
Unless the class being declared is abstract, all the abstract member
methods of each direct superinterface must be implemented (§8.4.8.1)
either by a declaration in this class or by an existing method
declaration inherited from the direct superclass or a direct
superinterface, because a class that is not abstract is not permitted
to have abstract methods (§8.1.1.1).
While the rule only talks about direct superclasses, it is technically also true for indirect superclasses, as method inheritance bubbles down through the hierarchy.
Given that equals() is implemented by Object and Object is the direct or indirect superclass of every class, you don't have to provide an implementation for equals().
I have a Java Interface InterfaceA that defines 3 methods with different signatures (2 of them are defaulted).
Another class defines a method like so:
public void f(InterfaceA ia) {
.....
}
and in the unit test this is how this is used:
f((ArgA) -> return ArgA.write())
How is this possible knowing that InterfaceA defines 3 methods?
According to the documentation for #FunctionalInterface, the fact that an interface implements n methods doesn't mean it doesn't qualify as a valid interface. The details of these methods is what matters.
Conceptually, a functional interface has exactly one abstract method.
Since default methods have an implementation, they are not abstract.
If an interface declares an abstract method overriding one of the
public methods of java.lang.Object, that also does not count toward
the interface's abstract method count since any implementation of the
interface will have an implementation from java.lang.Object or
elsewhere. (emphasis mine)
So, it depends on the interface in question. It sounds like your interface is defined appropriately.
Java doesn't support multiple inheritance because if two classes have same function name but different implementation and if a third class inherits these two classes and if it wants to use the method, then it will create a confusion on which method should be called. So java uses multiple interfaces concept. But my doubt is if two multiple interfaces also have the same function name but different implementation and if a third class implements these two interfaces and when it provides implementation to that method then is it not a problem, please explain?
Java interface only define the method name and have no implementation. The implementation of the methods is done in the class implementing the interface(s). Thus the problem is avoided.
You do have this problem a little bit, if two interfaces provide methods with the same signature that are supposed to do two different things. Interfaces do not just specify a method signature, after all, but also a contract how they should be implemented (which a compiler cannot enforce, though). Then you cannot really extend both interfaces, because your implementation can only provide one method (so it has to choose one of the two contracts to fulfill). But of course, this is not a problem for the runtime system, but more of your interface design.
A clash between two interfaces occurs when two methods have the same parameters but a different return type.
Example:
public class MultipleInterfaceClash {
public interface Foo {
String baz(int a, String x);
}
public interface Bar {
Double baz(int a, String x);
}
public class Confused implements Foo, Bar {
// Compile error: The return type is incompatible with
// MultipleInterfaceClash.Foo.baz(int, String)
public Double baz(int a, String x) {
return null;
}
}
}
It is not possible to implement both these interfaces.
Interfaces have no implementation.
Only method definition
public Interface a{
void a();
}
interface just provides a contract to the user, in this case the method signature.
The implementing classes must follow this contract. Hence, if two or more interfaces specify the same contract, then the implementing class do not have any issue as the implementation will serve the purpose.
Interfaces do not have any default implementation. Only method signature is specified.