Predicate<String> accepts a String and returns a boolean. How can you call a method of another object that is unrelated to the input object. The pre2 compiles i'm guessing because it will interpret it as
If pre3 worked then it would look like this:
Doesn't make any sense does it? that's why it won't compile.
If it was another object that had a method that accepts a String and returns a boolean then it will compile.
What you are doing in a Predicate<T> is taking a T an applying it to thetest() method. But test() takes a T as its parameter. So you have a T somewhere.
You are trying to find the equivalent of s.isEmpty(). The test(T) call must use the T somewhere, so it goes into the λ to work out where. It would usually execute s.isEmpty() in which case you write the method reference as String::isEmpty. That might look like a static method call, but it isn't because isEmpty() is an instance method. The T cannot be applied to the method because isEmpty() takes no parameters, so the no‑args method is called, and the T is transferred to become the object on which the method is called.
If you write str::isEmpty, the object name has already been used, so there is nowhere to pass an object anywhere.