Ответ на ваш вопрос. PrintStream.println(String)
- это метод экземпляра, подразумевающий, что для вызова метода требуется экземпляр.
При этом
Consumer<String> c = PrintStream::println
Java не знает, где найти PrintStream
экземпляр для вызова println()
при вызове c.accept(String)
. Код скомпилировался бы, если бы println
были static
в PrintStream
.
Это не та же история с
Consumer<String> c = System.out::println
, который уже указал экземпляр, на котором println
будет вызван (экземпляр System.out
).
Существуют случаи, когда экземпляр, для которого вызывается ссылка на метод, не требуется указывать явно, например (заимствование метода Object для простоты)
Consumer<String> c = String::notify; //notify is an instance method
Компилируется, потому что Java может использовать параметр, переданный в Consumer.accept
в качестве цели метода, поэтому String::notify
может использоваться для этой цели. Но все не так просто (например, notify
void), поэтому важно go через docs / spe c о том, как разрешаются ссылки на методы (это хорошее место для начала: https://docs.oracle.com/javase/tutorial/java/javaOO/methodreferences.html).