Why can't I create a #FunctionalInterface with a default method implementation?
#FunctionalInterface
public interface MyInterface {
default boolean authorize(String value) {
return true;
}
}
You can have default methods in a functional interface but its contract requires you to provide one single abstract method (or SAM). Since a default method have an implementation, it's not abstract.
Conceptually, a functional interface has exactly one abstract method.
Since default methods have an implementation, they are not abstract.
and
If a type is annotated with this annotation type, compilers are
required to generate an error message unless:
The type is an interface type and not an annotation type, enum, or
class.
The annotated type satisfies the requirements of a functional
interface.
Here you don't satisfy the functional interface's requirement, so you need to provide one abstract method. For example:
#FunctionalInterface
interface MyInterface {
boolean authorize(int val);
default boolean authorize(String value) {
return true;
}
}
Note that if you declare an abstract method overriding one of a public method from the Object's class it doesn't count, because any implementation of this interface will have an implementation of those methods through at least the Object's class. For example:
#FunctionalInterface
interface MyInterface {
default boolean authorize(String value) {
return true;
}
boolean equals(Object o);
}
does not compile.
A functional interface is an interface having a single abstract method. The entire purpose of defining functional interfaces is to enable the implementation of the single abstract method via lambda expressions which will effectively override that method which makes providing a default implementation for it pointless.
Having an interface consisting entirely of default methods raises multiple problems. There is the technical problem that the compiler can’t decide for a lambda expression which method to implement when there are multiple default methods and there is the semantic problem that an interface consisting entirely of default methods is not abstract. You can’t instantiate this default behavior as you can’t instantiate interfaces and are forcing programmers to create concrete classes just to invoke the default behavior, which, since interfaces are stateless, could be provided by a singleton instead:
#FunctionalInterface
public interface MyInterface {
static MyInterface DEFAULT = s->true;
boolean authorize(String value);
}
Note that you can have interfaces extending a functional interface and providing a default method, if you need. Still, if this results in creating an interface having no abstract methods I would question the design. You may compare with the discussion about marker interfaces with default methods. If the sub-interface will have different abstract methods than the functional interface, it’s a different story. There might be real use cases for this, but these sub-interfaces will also demonstrate why they shouldn’t be mixed with the functional base interface as a lambda expression will always implement the abstract method.
That's because #FunctionalInterface can have default methods, as many as you want. For example, consider the java.util.Function interface. It contains two default methods: compose and andThen. But there should be exactly one non-default method. Otherwise how compiler would know which of your default methods should be mapped to lambda?
I just want to add a few more points.
We can have any number of Abstract method in FuntionalInterface.
We can also have any number of Static method in FuntionalInterface.
We can also declare an abstract method overriding one of a public method from the Object's class but there must be some other custom abstract method in this functional interface too as shown in below code
#FunctionalInterface
public interface SAM {
public void helloSam();
default void xyz() {
System.out.println("xyz");
}
static void abc() {
System.out.println("abc");
}
static void abc1() {
System.out.println("abc1");
}
default void xyz1() {
System.out.println("xyz1");
}
boolean equals(Object o);
}
Related
Or in particular: What is the difference between
interface A {
void fa();
}
interface B extends A {
void fa();
void fb();
}
and
interface A {
void fa();
}
interface B extends A {
#Override
void fa();
void fb();
}
Does it effect the implementing class in any way?
No it should not. The class that implements interface B will still have to provide an implementation of void fa(); regardless whether interface B annotates the same method signature with #Override or not. Also, putting the #Override annotation in interface B doesn't make a lot of sense in this case because the annotation basically means that you are overriding the implementation that the super class gave to that method signature. Since Interface A nor Interface B provides an implementation to void fa() it doesen't make sense.
It would make sense if interface A provided a default implementation to void fa() For example:
interface A {
public default void fa(){
System.out.println("My default implementation");
}
}
In this case Interface B would be overriding the implementation given to fa() from Interface A by making it abstract again. The same goes when Interface A defines fa() as abstract and Interface B gives it an implementation by turning it into a default method.
The #Override annotation is just a reminder to the compiler to show you an error if you define something wrong. It doesn't affect anything. The good practise is to write it always.
Adding or omitting #Override doesn't change the overriding behaviour of the fa method. It's an override based on the name and parameter types (in this case none), nothing else. The return type needs to be compatible (covariant return), but is not part of the "is this an override or not" decision.
The #Override annotation is (mostly) used to verify that a method is overriding a method from a super type. If you omit it, there may be a warning from your IDE or other tooling like SonarQube, but the compiler doesn't care. If you add it incorrectly, that's when its true purpose kicks in - you'll get a compiler error.
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/
interface Rideable {
String getGait();
}
public class Camel implements Rideable {
int weight = 2;
String getGait() {
return " mph, lope";
}
void go(int speed) {++speed;
weight++;
int walkrate = speed * weight;
System.out.print(walkrate + getGait());
}
public static void main(String[] args) {
new Camel().go(8);
}
}
Upon compiling the above code I've got a compilation error, related to access modifier of getGait() method. Please explain, why should I declare getGait() with public access modifier?
getGait() of Camel implements a method of the Rideable interface. All interface methods are public by default (even if you don't specify it explicitly in the interface definition), so all implementing methods must be public too, since you can't reduce the visibility of the interface method.
In the interface you have method getGait() declared as public. Even you do not state a method as a public in interface it is public.
But in your class, you have declared this method as package private. It is not allowed, because it reduces the visibility of the implemented method.
To avoid this problem. either declare this method as public in your class, or remove declaration (implements Rideable) that your class implements the interface with this method signature.
According object oriented fundamentals, interface contains only public methods. so when you implements interface, you should declare it as a public , otherwise it give you compile time error.
Thanks.
One of the basic usage of interfaces can be to check conformance.For example a class implementing Comparable interface must provide compareTo method and hence providing a mechanism to compare objects of the class.
The reason these methods being public makes sense is that any class which utilizes this conformance must be able to use these methods without any restriction.For example sort method of Arrays class will be good enough to sort objects of a class only if it implements Comparable and exposes the compareTo method(If thats the mechanism you want to provide for sorting.Of course Comparator is also there). So in a nutshell, a contract is only good enough if its readable or usable in case of interfaces(thus making methods public imperative).
In Interface, the fields are implicitly public static final and the methods in an interface are by default public.
Please read the rules of Inheritance:
http://www.codejava.net/java-core/the-java-language/12-rules-of-overriding-in-java-you-should-know
One of which says, "The overriding method must not have more restrictive access modifier". So you are ovveriding the getGait() in Camel class. If you do not provide the access modifier in methods of class then by defaults its default. Which mean you are restricting the access modifier from public to default. Hence breaking the rule of ovveriding which is why its complaining.
I'm looking for a solution, that allows to protect the default methods from inheritance. The easiest solution could be - extend from class and etc... but in my case it's not possible.
Can someone suggest how to solve this problem? Could there be any workarounds?
Atm I have following code, which needs to be reworked (if/any possible):
public interface MyInterface1 {
default boolean isA(Object obj) {
return (boolean) obj.equals("A") ? true : false;
}
default boolean isB(Object obj) {
return (boolean) obj.equals("B") ? true : false;
}
}
public class MyClass extends MyLogic implements MyInterface, MyInterface1 {
// this class allows to inherit methods from both interfaces,
// but from my perspective i'd like to use the methods from MyInterface1 as it is,
// with a 'protection' from inheritance. is that possible?
}
You seem to want a way to write your interface so that implementing classes cannot provide their own implementations of its default methods. There is no way to do this, and indeed it runs counter to the purpose of interfaces in general and default members in particular.
The point of default methods is to provide a way to add methods to existing interfaces without instantly breaking all their existing implementations. Generally speaking, this is a binary compatibility issue, not a functionality issue. There's no particular reason to suppose in general that default implementations can provide the intended functionality, but without them, even old code that doesn't rely on the new methods at all is incompatible with interface revisions that add methods.
I think you have a factoring issue. Rather than trying to force classes to provide a specific implementation of a specific method -- which cannot even refer to that class's members, except possibly others defined by the same interface -- you should provide the common methods in a class of their own. After all, since you want all classes involved to provide identical implementations, it doesn't matter which class's implementations you actually use. Moreover, there is therefore no particular usefulness in marking any given class as providing implementations of the well-known methods.
Example:
public class MyImplementation1 {
public static boolean isA(Object obj) {
return obj.equals("A");
}
public static isB(Object obj) {
return obj.equals("B");
}
}
// Wherever needed, use as MyImplementation1.isA(o), etc.
You can do this even if you want these pre-baked implementations to operate in terms of the other methods of your interface. In that case, just add an argument to the fixed methods that provides the object to operate on. Perhaps that's what the obj arguments in your example were supposed to be; in that case, this may be closer to what you're after:
public interface MyInterface3 {
public String someInterfaceMethod();
}
public class MyImplementation2 {
public static boolean isA(MyInterface3 subject) {
return subject.someInterfaceMethod().equals("A");
}
public static boolean isB(MyInterface3 subject) {
return subject.someInterfaceMethod().equals("B");
}
}
You can't. At least if you restrict yourself to a pure-java-compiler solution.
And the reason is because it was not designed to do that: the purpose is to add new methods to existing interface (like java.util.Collection) without breaking the implementations. That way, we have sort(), stream(), forEach() on Collection.
If you were to allow such thing (forbidding implementation), then it would means a change in the interface would result in a compilation error for implementation (because they would override the method, method that would been rendered final). That was not the purpose.
There are several other options to achieve that, depending on your need:
Abstract class with final method being the previously default method.
Testing the default behavior using unit testing.
Testing the possible implementation and check they don't override it.
The last case can probably be done easily with Reflections: you would have to list all implementations, and check for each interface's default method that there is no overriding using Reflections.
I take it you mean you want to write a class that uses the default methods of an interface, but does not inherit them.
In your example code, you attempted to use the default methods by implementing the interface. When you implement an interface, by design you also inherit all its methods. This is the Liskov Substitution Principle. By implementing the interface you are telling your users that all instances of your class are substitutable for instances of the interface. But if the interface default methods weren't inherited, this wouldn't be true, so you would be lying to users of your class.
To have your class use the interface's default methods without inheriting them, don't implement the interface! Instead, use a helper class that does:
public interface MyInterface1 {
default boolean isA(Object obj) {
return obj.equals("A"); // or "A".equals(obj) to avoid NullPointerException
}
default boolean isB(Object obj) {
return obj.equals("B");
}
}
public class MyClass extends MyLogic implements MyInterface {
private static class Helper implements MyInterface1 {
void doSomeWork() {
// do something that calls isA() and isB()...
}
}
public void someMethodOfMyClass() {
// ...
Helper.doSomeWork();
// ...
}
}
No, This is not possible due to the way java implements the interface (pun intended). For more information as to the reason for this, see the answers to this question Why is "final" not allowed in Java 8 interface methods?
However here are some other ways to guide a developer not to override a default method:
A source code comment
//Do not inherit please
A javadoc comment
When I implement an Interface in Java, for instance:
public interface IColumnHeader {
public String getHeaderValue();
public String findColumnValueFromHeaderValue(String parseFrom);
}
the following enum implements the above interface:
public enum FileColumnDwellTime implements IColumnHeader {
REPORTER_USER_ID {
#Override
public String getHeaderValue() {
return "reporter_user_id";
}
#Override
public String findColumnValueFromHeaderValue(String parseFrom) {
return parseFrom;
}
};
}
Why does implementing an interface in Java and implementing the methods from the interface introduce the #Override annotation. Isn't that a total misnomer?
Shouldn't that annotation actually be called something like "#Implementation"?
The #Override annotation would be more apt for subclasses that actually override superclass methods that are predefined. In the case of simply implementing a method from an interface, there is no actual overriding being done.
Am I right?
(If I were the JLS writers for Java 9, I would have a new annotation called #Implementation that would "subclass" the #Override annotation, in the case of implementing methods from interfaces, and the like.)
Taking a look at the JLS, it just seems to be how it's defined. I'm looking at JLS 8, not sure if the section I'm going to quote was different in earlier versions (although I highly doubt it will, since interface interactions shouldn't have changed). From section 8.4.8.1:
An instance method mC declared in or inherited by class C, overrides from C another
method mI declared in an interface I, iff all of the following are true:
I is a superinterface of C.
mI is an abstract or default method.
The signature of mC is a subsignature (§8.4.2) of the signature of mI.
So at least based on this, the #Override annotation makes sense, since it denotes an instance method that overrides a method declared in an interface, based on the definitions in the JLS.
Unfortunately, I can't give an authoritative answer as to why this is called overriding, but here's sort of how it works in my head:
If you inherit an abstract method (like one in an interface), your class implicitly contains the signature for that method in its body. When you implement the method corresponding to that signature, you replace (and thus override) the inherited abstract method signature with one corresponding to a concrete implementation. So it makes sense to have #Override, right?
In addition, this way #Override would work for overridden methods regardless of whether they were technically an implementation or "truly" overridden. And why make more work for yourself (and compiler designers) than you have to?
I know that that's a rather bad view of how inheritance works, but I hope it makes sense.
So I guess in the end, I would say you are wrong. There is overriding being done. But I wouldn't say it's immediately obvious why that is the case. Interesting question!