Quick Java Anonymous function/class question

Viewed 588

I know how anonymous functions work in JS and all but a bit confused on parts of it in Java.

So below I have an anonymous class (I'm just using the Thread class as an example to what I've seen), where I override the run() function and then call .start() on that class.

new Thread() {
    @Override
    public void run() {
        System.out.println("Hello from the anonymous class thread");
    }
}.start();

So this works, but IntelliJ wants to me re-write it as this:

new Thread(() -> System.out.println("Hello from the anonymous class thread")).start();

I get most of this syntax, but just a bit confused as to how the run() function is being overridden. From my understanding, there is no parameter being passed into the Thread class (so nothing being passed into the constructor I'm assuming). Now where I'm confused is here. It doesn't state anywhere that it is overriding the run() function. Is this a special case for the Thread class or is there something I am missing?

Hope that I explained this clearly and thanks in advance!

2 Answers

The syntax that IntelliJ proposes to you is not more of an "oblique" translation of your original code, and does not actually override Thread.run like your original code does.

Your original code creates an anonymous subclass of Thread with run overridden, whereas the proposed syntax by IntelliJ calls this constructor of Thread that accepts a Runnable. The lambda expression represents the Runnable. If we "expand" the lambda expression into an anonymous class, we will be actually doing this:

new Thread(new Runnable() {
    @Override
    public void run() {
        System.out.println("Hello from the anonymous class thread");
    }
}).start();

So we are creating an anonymous implementation of Runnable, and implementing Runnable.run instead.

It doesn't state anywhere that it is overriding the run() function.

True, but run is the only abstract method in the Runnable interface, so Java is able to figure out that you are overriding that method.

The run() function is being overridden implicitly because it's the only method of the Runnable interface, which makes it a functional interface. A functional interface has exactly one abstract method. This special property of an interface allows you to implement it implicitly using a lambda expression. The compiler knows you're providing an implementation of the Runnable.run() method, because it's the only method inside the interface.

If you take a look at the Runnable interface, you'll see that it is decorated with the @FunctionalInterface annotation. This annotation ensures that the decorated interface can never have more than one abstract method (or else the compiler will fail). Note that this annotation is not required in order for the implicit lambda feature to work.

Related