javafunctional-interfacesupplier

Why is it compiled? - T = Supplier<T>?


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.


Solution

  • 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();
        }
    };