Runnable::new vs new Runnable()

  • A+
Category:Languages

Why doesn't the first of the following examples work?

  • run(R::new); method R.run is not called.
  • run(new R()); method R.run is called.

Both examples are compiled-able.

public 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();   }    static class R implements Runnable {        R() {           System.out.println("R constructor runs");       }        @Override       public void run() {           System.out.println("R.run runs");       }   } } 

The output is:

  R constructor runs   -----------------------   R constructor runs   R.run runs 

In the first example the R constructor is called, it returns lambda (which is not object):

Runnable::new vs new Runnable()

But then how is it possible, that the example is compiled successfully?

 


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:

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); 

Comment

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: