Ваш метод run
принимает экземпляр Runnable
, и это объясняет, почему run(new R())
работает с реализацией R
.
R::new
не эквивалентно new R()
. Он может соответствовать сигнатуре Supplier<Runnable>
(или аналогичным функциональным интерфейсам), но R::new
нельзя использовать как Runnable
, реализованный с вашим классом R
.
Версия вашего run
метода, который может принимать R::new
, может выглядеть так (но это будет излишне сложно):
void run(Supplier<Runnable> r) {
r.get().run();
}
Почему он компилируется?
Поскольку компилятор может сделать Runnable
из вызова конструктора, и это будет эквивалентно этой версии лямбда-выражения:
new ConstructorRefVsNew().run(() -> {
new R(); //discarded result, but this is the run() body
});
То же относится и к этим утверждениям:
Runnable runnable = () -> new R();
new ConstructorRefVsNew().run(runnable);
Runnable runnable2 = R::new;
new ConstructorRefVsNew().run(runnable2);
Но, как вы можете заметить, Runnable
, созданный с помощью R::new
, просто вызывает new R()
в своем теле run
метода.
Допустимое использование ссылки на метод для выполнения R#run
может использовать экземпляр, подобный этому (но вы наверняка предпочтете использовать экземпляр r
напрямую, в этом случае):
R r = new R();
new ConstructorRefVsNew().run(r::run);