I'm having a hard time sorting out why lambda expressions are assignable to some functional interfaces, but not others. An example, using some functional interfaces from the Metrics library:
Gauge<Double> foo = () -> { return null; };
RatioGauge bar = () -> { return null; };
The second statement has a compile error (in Eclipse):
The target type of this expression must be a functional interface
As far as I can tell, RatioGauge is a functional interface. Am I missing something?
An abstract class (even if it only has one abstract method) is not a functional interface. Only an interface can be one.
From JLS 9.8:
A functional interface is an interface that has just one abstract method (aside from the methods of Object)... (emphasis added)
The original idea was to let abstact classes be expressed as a lambda; they were called "SAM types," which stood for "single abstract method." That turned out to be a difficult problem to solve efficiently. This thread talks a bit about why; basically, the base class's constructor made it difficult.
A function interface can have only ONE abstract method (besides the methods from Object class).
Source code for Gauge.java= http://grepcode.com/file/repo1.maven.org/maven2/com.codahale.metrics/metrics-core/3.0.0/com/codahale/metrics/Gauge.java#Gauge
Source code for RatioGauge.java= http://grepcode.com/file/repo1.maven.org/maven2/com.codahale.metrics/metrics-core/3.0.0/com/codahale/metrics/RatioGauge.java
Notice that Gauge.java only has one abstract method while RatioGauge has many methods.
Related
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/
I was just curious if they are treated any differently.
For example if we have:
The interface:
public interface Test {
public void method();
}
And the abstract class:
public abstract class Test {
public abstract void method();
}
Will the JVM treat these classes any differently? Which of the two takes up more disk space during storage, which one will use up the most runtime memory which one does more operations(performs better).
This question isn't about when to use interfaces or abstract classes.
Yes, they are different.
With an interface, clients could implement it aswell as extend a class:
class ClientType implements YourInterface, SomeOtherInterface { //can still extend other types
}
With a class, clients will be able to extend it, but not extend any other type:
class ClientType extends YourClass { //can no longer extend other types
}
Another difference arises when the interface or abstract class have only a single abstract method declaration, and it has to do with anonymous functions (lambdas).
As #AlexanderPetrov said, an interface with one method can be used as a functional interface, allowing us to create functions "on-the-fly" where ever a functional interface type is specified:
//the interface
interface Runnable {
void run()
}
//where it's specified
void execute(Runnable runnable) {
runnable.run();
}
//specifying argument using lambda
execute(() -> /* code here */);
This cannot be done with an abstract class.
So you cannot use them interchangably. The difference comes in the limitations of how a client can use it, which is enforced by the semantics of the JVM.
As for differences in resource usage, it's not something to worry about unless it's causing your software problems. The idea of using a memory-managed language is to not worry about such things unless you are having problems. Don't preoptimize, I'm sure the difference is negligable. And even if there is a difference, it should only matter if it may cause a problem for your software.
If your software is having resource problems, profile your application. If it does cause memory issues, you will be able to see it, as well as how much resources each one consumes. Until then, you shouldn't worry about it. You should prefer the feature that makes your code easier to manage, as opposed to which consumes the least amount of resources.
JVM internals and memory representation
It will be almost the same for the JVM. My statement is based on Chapter 4 - Class file Format. As seen from the attached documentation the JVM is making difference between a class and interface, by the access_flags. If you have a Simple interface with just one method and a simple abstract class with just one method. Most of the fields in this format will be the same (empty) and the main difference will be the access_flags.
Default constructor generation abstract class
As #Holger pointed out, another small difference between the Interface and Abstract class is that ordinary classes require a constructor. The Java compiler will generate a default constructor for the Abstract class which will be invoked for each of its subclasses. In that sense the abstract class definition will be slightly bigger compared to the interface.
https://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html
ClassFile {
u4 magic;
u2 minor_version;
u2 major_version;
u2 constant_pool_count;
cp_info constant_pool[constant_pool_count-1];
u2 access_flags;
u2 this_class;
u2 super_class;
u2 interfaces_count;
u2 interfaces[interfaces_count];
u2 fields_count;
field_info fields[fields_count];
u2 methods_count;
method_info methods[methods_count];
u2 attributes_count;
attribute_info attributes[attributes_count];
}
Besides the multiple inheritance of interfaces, another difference is that in Java8 abstract class with only one method is not a Functional interface.
#FunctionalInterface
public interface SimpleFuncInterface {
public void doWork();
}
execute(SimpleFuncInterface function) {
function.doWork();
}
execute(()->System.out.printline("Did work"));
Same can not be achieved with abstract class.
Interfaces - lack of "Openness to extension".
Up to Java 8 Interfaces have been criticized for their lack of extensibility. If you change the interface contract you need to refactor all clients of an interface.
One example that comes to mind is Java MapReduce API for Hadoop, which
was changed in 0.20.0 release to favour abstract classes over
interfaces, since they are easier to evolve. Which means, a new method
can be added to abstract class (with default implementation), with out
breaking old implementations of the class.
With the introduction of Java 8 Interface Default method
this lack of extensibility has been addressed.
public interface MyInterface {
int method1();
// default method, providing default implementation
default String displayGreeting(){
return "Hello from MyInterface";
}
}
With Java 8 new methods can be added both to interfaces and abstract classes without breaking the contract will the client classes.
http://netjs.blogspot.bg/2015/05/interface-default-methods-in-java-8.html
They are different in implementation
you can only extend only one abstract class
On the other hand you can implement multiple interfaces at the same time
You need to implement all method present in an interface
for abstract it may provide some default implementation so you are independent whether you want to implement it again or just used the default implementation
If you talking about performance, then sometime ago there was an opinion that interfaces are slower than abstract classes. But now JIT makes no difference between them.
Please, see this answer for more details.
I came across a new term in Java 8: "functional interface". I could only find one use of it while working with lambda expressions.
Java 8 provides some built-in functional interfaces and if we want to define any functional interface then we can make use of the #FunctionalInterface annotation. It will allow us to declare only a single method in the interface.
For example:
#FunctionalInterface
interface MathOperation {
int operation(int a, int b);
}
How useful it is in Java 8 other than just working with lambda expressions?
(The question here is different from the one I asked. It is asking why we need functional interfaces while working with lambda expressions. My question is: What are the other uses of functional interfaces besides use with lambda expressions?)
#FunctionalInterface annotation is useful for compilation time checking of your code. You cannot have more than one method besides static, default and abstract methods that override methods in Object in your #FunctionalInterface or any other interface used as a functional interface.
But you can use lambdas without this annotation as well as you can override methods without #Override annotation.
From docs
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
This can be used in lambda expression:
public interface Foo {
public void doSomething();
}
This cannot be used in lambda expression:
public interface Foo {
public void doSomething();
public void doSomethingElse();
}
But this will give compilation error:
#FunctionalInterface
public interface Foo {
public void doSomething();
public void doSomethingElse();
}
Invalid '#FunctionalInterface' annotation; Foo is not a functional
interface
The documentation makes indeed a difference between the purpose
An informative annotation type used to indicate that an interface type declaration is intended to be a functional interface as defined by the Java Language Specification.
and the use case
Note that instances of functional interfaces can be created with lambda expressions, method references, or constructor references.
whose wording does not preclude other use cases in general. Since the primary purpose is to indicate a functional interface, your actual question boils down to “Are there other use cases for functional interfaces other than lambda expressions and method/constructor references?”
Since functional interface is a Java language construct defined by the Java Language Specification, only that specification can answer that question:
JLS §9.8. Functional Interfaces:
…
In addition to the usual process of creating an interface instance by declaring and instantiating a class (§15.9), instances of functional interfaces can be created with method reference expressions and lambda expressions (§15.13, §15.27).
So the Java Language Specification doesn’t say otherwise, the only use case mentioned in that section is that of creating interface instances with method reference expressions and lambda expressions. (This includes constructor references as they are noted as one form of method reference expression in the specification).
So in one sentence, no, there is no other use case for it in Java 8.
As others have said, a functional interface is an interface which exposes one method. It may have more than one method, but all of the others must have a default implementation. The reason it's called a "functional interface" is because it effectively acts as a function. Since you can pass interfaces as parameters, it means that functions are now "first-class citizens" like in functional programming languages. This has many benefits, and you'll see them quite a lot when using the Stream API. Of course, lambda expressions are the main obvious use for them.
Not at all. Lambda expressions are the one and only point of that annotation.
A lambda expression can be assigned to a functional interface type, but so can method references, and anonymous classes.
One nice thing about the specific functional interfaces in java.util.function is that they can be composed to create new functions (like Function.andThen and Function.compose, Predicate.and, etc.) due to the handy default methods they contain.
An interface with only one abstract method is called Functional Interface.
It is not mandatory to use #FunctionalInterface, but it’s best practice to use it with functional interfaces to avoid addition of extra methods accidentally. If the interface is annotated with #FunctionalInterface annotation and we try to have more than one abstract method, it throws compiler error.
package com.akhi;
#FunctionalInterface
public interface FucnctionalDemo {
void letsDoSomething();
//void letsGo(); //invalid because another abstract method does not allow
public String toString(); // valid because toString from Object
public boolean equals(Object o); //valid
public static int sum(int a,int b) // valid because method static
{
return a+b;
}
public default int sub(int a,int b) //valid because method default
{
return a-b;
}
}
Functional Interface:
Introduced in Java 8
Interface that contains a "single abstract" method.
Example 1:
interface CalcArea { // --functional interface
double calcArea(double rad);
}
Example 2:
interface CalcGeometry { // --functional interface
double calcArea(double rad);
default double calcPeri(double rad) {
return 0.0;
}
}
Example 3:
interface CalcGeometry { // -- not functional interface
double calcArea(double rad);
double calcPeri(double rad);
}
Java8 annotation -- #FunctionalInterface
Annotation check that interface contains only one abstract method. If not, raise error.
Even though #FunctionalInterface missing, it is still functional interface (if having single abstract method). The annotation helps avoid mistakes.
Functional interface may have additional static & default methods.
e.g. Iterable<>, Comparable<>, Comparator<>.
Applications of Functional Interface:
Method references
Lambda Expression
Constructor references
To learn functional interfaces, learn first default methods in interface, and after learning functional interface, it will be easy to you to understand method reference and lambda expression
You can use lambda in Java 8
public static void main(String[] args) {
tentimes(inputPrm - > System.out.println(inputPrm));
//tentimes(System.out::println); // You can also replace lambda with static method reference
}
public static void tentimes(Consumer myFunction) {
for (int i = 0; i < 10; i++)
myFunction.accept("hello");
}
For further info about Java Lambdas and FunctionalInterfaces
#FunctionalInterface is a new annotation are released with Java 8 and provide target types for lambda expressions and it used on compilation time checking of your code.
When you want to use it :
1- Your interface must not have more than one abstract methods, otherwise compilation error will be given.
1- Your interface Should be pure, which means functional interface is intended to be implemented by stateless classes, exmple of pure is Comparator interface because its not depend on the implementers state, in this case No compilation error will be given, but in many cases you will not be able to use lambda with this kind of interfaces
The java.util.function package contains various general purpose functional interfaces such as Predicate, Consumer, Function, and Supplier.
Also please note that you can use lambdas without this annotation.
Beside other answers, I think the main reason to "why using Functional Interface other than directly with lambda expressions" can be related to nature of Java language which is Object Oriented.
The main attributes of Lambda expressions are: 1. They can be passed around 2. and they can executed in future in specific time (several times). Now to support this feature in languages, some other languages deal simply with this matter.
For instance in Java Script, a function (Anonymous function, or Function literals) can be addressed as a object. So, you can create them simply and also they can be assigned to a variable and so forth. For example:
var myFunction = function (...) {
...;
}
alert(myFunction(...));
or via ES6, you can use an arrow function.
const myFunction = ... => ...
Up to now, Java language designers have not accepted to handle mentioned features via these manner (functional programming techniques). They believe that Java language is Object Oriented and therefore they should solve this problem via Object Oriented techniques. They don't want to miss simplicity and consistency of Java language.
Therefore, they use interfaces, as when an object of an interface with just one method (I mean functional interface) is need you can replace it with a lambda expression. Such as:
ActionListener listener = event -> ...;
Functional Interfaces: An interface is called a functional interface if it has a single abstract method irrespective of the number of default or static methods. Functional Interface are use for lamda expression. Runnable, Callable, Comparable, Comparator are few examples of Functional Interface.
KeyNotes:
Annotation #FunctionalInterface is used(Optional).
It should have only 1 abstract method(irrespective of number of default and static
methods).
Two abstract method gives compilation error(Provider #FunctionalInterface annotation is
used).
This thread talks more in detail about what benefit functional Interface gives over anonymous class and how to use them.
Consider the following little example:
package prv.rli.codetest;
import java.lang.reflect.Method;
public class BreakingInterfaces {
interface Base {
BaseFoo foo();
interface BaseFoo {
}
}
interface Derived extends Base {
DerivedFoo foo();
interface DerivedFoo extends BaseFoo {
}
}
public static void main(String[] args) {
dumpDeclaredMethods(Derived.class);
}
private static void dumpDeclaredMethods(Class<?> class1) {
System.out.println("---" + class1.getSimpleName() + "---");
Method[] methods = class1.getDeclaredMethods();
for (Method method : methods) {
System.out.println(method);
}
System.out.println("----------");
}
}
If you compile the above example with jdk1.7.0.55 the output is:
---Derived---
public abstract BreakingInterfaces$Derived$DerivedFoo BreakingInterfaces$Derived.foo()
----------
But when using jdk1.8.0.25 the output is:
---Derived---
public abstract prv.rli.codetest.BreakingInterfaces$Derived$DerivedFoo prv.rli.codetest.BreakingInterfaces$Derived.foo()
public default prv.rli.codetest.BreakingInterfaces$Base$BaseFoo prv.rli.codetest.BreakingInterfaces$Derived.foo()
----------
Does anybody know, whether this is a bug in jdk1.8.0.25 or why the public default Method resurfaces here?
getDeclaredMethods() behaves correctly here as it tells you exactly what it has found in the class. If you feed in an interface compiled with Java 7 target (or an older compiler) you will see no difference to the output of the Java 7 implementation of getDeclaredMethods().
It’s the compiler which behaves differently. When compiling such a sub-interface in Java 8, a bridge method will be generated which will not be generated for a Java 7 target as it is not even possible for the Java 7 target.
The reason why bridge methods are generated for interfaces now is that you usually have more implementation classes than interfaces, therefore having a default bridge method in the interface saves you from adding that bridge method to every implementation. Further, it makes lambda class generation much easier if there is only one abstract method and no bridge method to implement.
When an interface hierarchy requires bridge methods but provides no defaults, the compiler has to generate code using LambdaMetafactory.altMetafactory rather than LambdaMetafactory.metafactory specifying every bridge method that is required.
Pardon the furstration, but it must be in a parallel universe where the Javadoc wording adequately explains this behavior: https://docs.oracle.com/javase/8/docs/api/java/lang/Class.html#getDeclaredMethods--. An array of "all the declared methods" turns out to be an array of "all declared methods by the user and by some under-the-hood implementation detail explained on StackOverflow". Even worse, I'm seeing something weird about annotations: I'm overriding a generic method while applying an annotation, and both abstract&default methods returned by getDeclaredMethods() have the annotation, but only the abstract one has the correct non-generic parameters. So it seems to me this implementation detail partly defeats the purpose of searching for a method by annotation.
I just started figuring out the difference between implicit and explicit interface implmentation in .Net. Since I come from a Java background the idea is still a bit confusing. I am hoping knowing which Java does will make it more obvious what the difference is. I am assuming the Java is explicit???
Nope Java is implicit. Explicit is where you are implementing multiple interfaces that have the same method signatures in them and you explicitly state which interface the implementation is for.
An example from MSDN:
public class SampleClass : IControl, ISurface
{
void IControl.Paint()
{
System.Console.WriteLine("IControl.Paint");
}
void ISurface.Paint()
{
System.Console.WriteLine("ISurface.Paint");
}
}
Here we have two Paint() methods, one from each interface. In Java you can only have one Paint() implementation. In C# you have the option of implementing versions for each interface so you get different behaviour depending how the class is called.
So if I called:
SampleClass c = new SampleClass();
((IControl)c).Paint();
((ISurface)c).Paint();
I'd get "IControl.Paint" printed out followed by "ISurface.Paint" printed out.
In Java there is no distinction between explicit and implicit. If you have two interfaces that both declare a method with the same signature, and a class that implements both interface, then a method in the class with the correct signature implements the method in BOTH interfaces.