Normally I use Eclipse for my developments and everything works fine as expected. Today I tried to build my project outside Eclipse, using just Maven and JDK 8u112 (the latest at this moment). I got a "funny" compile error in one of my demos: MaxOriginDistanceByQuadrant.java
To be more clear about the problem, I tried to re-create a simpler/single source to reproduce the problem.
And it is:
A javac StreamProblem.java using directly the JDK 8u112 gives the following very "funny" error:
Note that this exact code perfectly compiles and works in Eclipse (the latest Neon.2 Release (4.6.2) Build id: 20161208-0600).
I noticed that I can solve the problem using the so called type witness on the naturalOrder():
The problem me thinks, is that if you look at the API of collect, Collectors.groupingBy and Collectors.mapping, the class parameter <T> in the mapping is independant of the class parameter <T> as used in the groupingBy. That is why java does not recognize the mehod getNum of obj2, ince it does not know what type obj2 is, This code works:
by helping java a little by revealing the type of obj2 that we are dealing with. That is why using 'MyObj::getNum' also suffices, and if you use Comparator<Double> it somehow also recognizes MyObj, although I do not completely understand what is happening in that case.
There are three kinds of actuaries: those who can count, and those who can't.
The reason why it works using method reference is obvious: method references include both the parameters and return types, so it gives the compiler much more information than needed. As Piet said, specifying the argument type for the mapper function is enough to make type inference work.
You have in fact many possible solutions:
1) using a method reference MyObj::getNum
2) specifying the parameter type for the mapper: (MyObj obj2) -> obj2.getNum()
3) using a parameterized method call: Collectors.maxBy(Comparator.<Double>naturalOrder())
4) Using a named Function:
5) Using an named Comparator for the downstream Collector:
Thee are probably many other possibilities to help the compiler inferring the Double type. The best one is obviously using method references.
This said, your very question was "is it a JDK bug?". The answer is no. It might be an Eclipse bug, depending on what were the requirements. Eclipse has its own compiler, and this compiler is (as you noted) not fully compatible with Java. So if the requirement for the Eclipse compiler was to be compatible with Java, it's an Eclipse bug. If the requirement was to be compatible with the Java 8 specification only, it's a feature.
The official Reference Implementations for Java SE 8 (JSR 337) are based solely upon open-source code available from the JDK 8 Project in the OpenJDK Community.
About one year ago, I submitted an issue to the Eclipse development team about the inverse problem: places were the Eclipse compiler was unable to infer types although Oracle JDK and OpenJDK could. The issue was rejected because they said it was not Eclipse which was not compatible, it was Oracle JDK that was not conform to the spec.
This obviously was not a big problem. An IDE with restrictions is fine. But an IDE that allows more that what the compiler used in production can accept is much more problematic. This shows that in any case, programmers should either avoid using Eclipse or compile with the JDK used in the build chain before submitting their work.
This, by the way, is not a problem specific to Eclipse. Programmers should develop with the same version of the JDK that the one used in production. Or at least, they should compile their code and run their tests locally using the correct version before submitting.
It is difficult to free fools from the chains they revere - Voltaire. tiny ad:
a bit of art, as a gift, that will fit in a stocking