[I'm reviewing the chapter 4 about streams of the book OCP: Oracle Certified Professional Java SE 8 Programmer II Study Guide and I have some difficulties with the excerpt about the mapping collector on page 223. I use here a simplified version of the proposed example.]
Can someone explain me why the following code doesn't compile:
while the following compiles without problems:
The compiler error is not really clear to me:
non-static method length() cannot be referenced from a static context
I have tried a lot of examples using the first syntax and no problem so far. What is wrong with this particular example here?
Good question! You can only use method references when Java can infer the type. The problem here is that the Comparator isn't specific enough.
You can tell that Java is relying on the comparator to determine the return type because neither of these compile:
Going back to your example, if you tell Java that the comparator is dealing with Strings, it has enough information to use to determine what the method references should be:
It is weird that it works without a method reference. The difference there is you have an actual String in the lambda version so Java knows which type/method you want. Whereas the method reference X::Y could expand to a static method X.y(a) or an instance method on type X a.y(). In your example, it doesn't know whether to use String.length(s) or s.length(). We know because one doesn't exist, but Java isn't that smart when compiling.
Well, if I may, the reason the following code doesn't compile has less to do with the comparator (or the lack of comparator in this case) than the type of Map used.
If I replace the previous code with the following, no problem.
But anyway, I agree that the comparator used can help in determining the type and the method reference for grouping.
However, I can't stop thinking this is a little bit weird as the example you gave compiles but the following does not:
And given that I can only assume you tested the examples that are in the book before you inserted them, I would dare to say it is a problem with Java itself.
In the same idea, the code as stated on page 223 (not very different from the one above) doesn't compile either for me (even not with a lambda or an explicit Comparator<String>).
OK, thanks for your help. Since we have a Stream<Integer>, I will consider Java can infer the type for the method references used, as written in the book. But, hopefully, the exam won't test such aspects of the language. After all
[...] it is the most complicated thing you should expect to see on the exam.
I didn't know the behavior could change across Java updates though. Good to know.