Runnable::new vs new Runnable() Runnable::new vs new Runnable() java java

Runnable::new vs new Runnable()


Your run method takes a Runnable instance, and that explains why run(new R()) works with the R implementation.

R::new is not equivalent to new R(). It can fit the signature of a Supplier<Runnable> (or similar functional interfaces), but R::new cannot be used as a Runnable implemented with your R class.

A version of your run method that can takeR::new could look like this (but this would be unnecessarily complex):

void run(Supplier<Runnable> r) {    r.get().run();}

Why does it compile?

Because the compiler can make a Runnable out of the constructor call, and that would be equivalent to this lambda expression version:

new ConstructorRefVsNew().run(() -> {    new R(); //discarded result, but this is the run() body});

The same applies to these statements:

Runnable runnable = () -> new R();new ConstructorRefVsNew().run(runnable);Runnable runnable2 = R::new;new ConstructorRefVsNew().run(runnable2);

But, as you can notice, the Runnable created with R::new does just call new R() in its run method body.


A valid use of a method reference to execute R#run could use an instance, like this (but you'd surely rather use the r instance directly, in this case):

R r = new R();new ConstructorRefVsNew().run(r::run);


The first example:

new ConstructorRefVsNew().run(R::new);

is more or less equivalent to:

new ConstructorRefVsNew().run( () -> {new R();} );

The effect is you just create an instance of R but do not call its run method.


Compare two calls:

((Runnable)() -> new R()).run();new R().run();

By ((Runnable)() -> new R()) or ((Runnable) R::new) , you create a new Runnable which does nothing1.

By new R(), you create an instance of the R class where the run method is well-defined.


1 Actually, it creates an object of R which has no impact on execution.


I was thinking of treating 2 invocations identically without modifying the main method. We would need to overload run(Runnable) with run(Supplier<Runnable>).

class ConstructorRefVsNew {    public static void main(String[] args) {        new ConstructorRefVsNew().run(R::new);        System.out.println("-----------------------");        new ConstructorRefVsNew().run(new R());    }    void run(Runnable r) {        r.run();    }    void run(Supplier<Runnable> s) {        run(s.get());    }    static class R implements Runnable { ... }}