I have an 'Animal' interface and 'Dog' class that implements 'Animal'.
public interface Animal {
void makeVoice();
}
public class Dog implements Animal {
@Override
public void makeVoice() {
System.out.println("aou aou");
}
}
In my main method, I wrote the following lines.
public class Main {
public static void main(String[] args) {
Animal dog = Dog::new; // How is it compiled? it should be Supplier<Animal>
dog.makeVoice(); // Doesn't call because 'dog' holds lambda expression (Supplier<Animal>) and not the actual 'Dog' class.
}
}
Why is it possible that Animal can hold Supplier?
I expected that it doesn't compile.
The constructor for Dog
satisfies the Animal
functional interface. The parameter types match as both makeVoice
and the default constructor for Dog
take no parameters. The constructor call is also void-compatible (it matches the void
return type) because a class instance creation expression is an expression statement.
The code is essentially equivalent to the following and it creates an implementation of Animal
, not Supplier
:
Animal dog = () -> new Dog();
// or equivalently, as the created Dog instance is ignored:
Animal dog = () -> {
new Dog();
};
As an anonymous class, it would look like this:
Animal dog = new Animal() {
@Override
public void makeVoice() {
new Dog();
}
};