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