Ваш 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
созданный с [1 118], действительно просто звонит new R()
в run
тело метода.
А допустимое использование ссылки метода для выполнения R#run
могло использовать экземпляр, как это (но Вы будете, конечно, скорее использовать r
экземпляр непосредственно, в этом случае):
R r = new R();
new ConstructorRefVsNew().run(r::run);
Первый пример:
new ConstructorRefVsNew().run(R::new);
более или менее эквивалентно:
new ConstructorRefVsNew().run( () -> {new R();} );
эффект - Вы, просто создают экземпляр R, но не называют run
метод.
Сравните два вызова:
((Runnable)() -> new R()).run();
new R().run();
((Runnable)() -> new R())
или ((Runnable) R::new)
, Вы создаете новое Runnable
, который ничего не делает <глоток> 1 глоток>.
new R()
, Вы создаете экземпляр R
класс , где run
метод четко определен.
<глоток> <глоток> 1 глоток> На самом деле, это создает объект R
, который не оказывает влияния на выполнение.
я думал об обработке 2 вызовов тождественно, не изменяя main
метод. Мы должны были бы перегрузиться run(Runnable)
с [1 111].
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 { ... }
}
run
метод ожидает Runnable
.
легкий случай new R()
. В этом случае Вы знаете, что результатом является объект самого типа R
. R
, выполнимое, он имеет run
метод, и это - то, как Java видит его.
, Но когда Вы передаете R::new
, что-то еще происходит. Что Вы говорите, что это должно создать анонимный объект, совместимый с Runnable
, чей run
метод выполняет операцию, Вы передали его.
операция Вы передали его, не R
run
метод. Операция является costructor [1 112]. Таким образом это похоже на Вас, передали его анонимный класс как:
new Runnable() {
public void run() {
new R();
}
}
(Не все подробности являются тем же, но это - самая близкая "классическая" конструкция Java).
R::new
при вызове, вызовы new R()
. Ничто больше, ничто меньше.