Consider the following self-contained sample:
package bloopers;
import java.lang.annotation.Annotation;
public final class Blooper5
{
interface Converter<T,F>
{
T convert( F from );
}
interface Identifier<T>
{
}
static class ConvertingIdentifier<F,T> implements Identifier<F>
{
ConvertingIdentifier( Converter<T,F> converter )
{
}
}
static final class AnnotationIdentifier
{
Identifier<Annotation> I1 = new ConvertingIdentifier<>(
a -> a.annotationType() );
Identifier<Annotation> I2 = new ConvertingIdentifier<>(
Annotation::annotationType ); //<-- ERROR
Identifier<Annotation> I3 = new ConvertingIdentifier<>(
(Converter<Class<? extends Annotation>,Annotation>)
Annotation::annotationType );
}
}
The code above compiles just fine under the following:
javac
from the command line.IntelliJ IDEA
configured to use the javac
compiler.But it fails to compile with the following:
Eclipse
IntelliJ IDEA
configured to use the Eclipse
compiler.Eclipse fails to compile the line marked with <-- ERROR
, giving the following message:
The constructor Blooper5.ConvertingIdentifier<Annotation,Class<capture#5-of ? extends Annotation>>(Blooper5.Converter<Class<? extends Annotation>,Annotation>) is undefined
Admittedly, this code really pushes the generic parameter type inference capabilities of the compiler, but still, I would like to know precisely what the discrepancy is, no matter how small.
Some exposure of my methods in case someone manages to see something wrong that I fail to see:
The command I used to compile with javac was "c:\Program Files\Java\jdk1.8.0_40\bin\javac" Blooper5.java
.
I have version 14.1 of IntelliJ IDEA. Under Project Structure/SDKs
I only have "1.8" which points to C:\Program Files\Java\jdk1.8.0_40
and under Project Structure/Modules
the specific module is configured to use the "Project SDK (1.8)" which lists as 1.8 (java version "1.8.0_40")
.
As for Eclipse, I am using Eclipse for RCP and RAP Developers - Version: Luna Release (4.4.0) - Build id: 20140612-0600
. Under Preferences/Java/Installed JREs
I only have jdk1.8.0_40, and it is the default. Under Execution Environments
it is also checked as a "Compatible JRE" of "JavaSE-1.8". And in my Project/Properties/Java Build Path/Libraries
the "JRE System Library" is [jdk1.8.0_40]
.
More noteworthy facts:
It is not just me; it also fails on a colleague's (very similar) eclipse installation.
IntelliJ IDEA says that the lambda expression a -> a.annotationType()
can be replaced with a method reference, but if asked to do so, it does not convert it to Annotation::annotationType
; instead, it converts it to (Converter<Class<? extends Annotation>, Annotation>) Annotation:: annotationType
.
So, the question:
What is causing these discrepancies between Eclipse and the others, and what can be done to eliminate these discrepancies?
(Obviously, the goal is to eliminate the unfortunately too frequently occurring scenario where one developer commits code which fails to compile on another developer's IDE.)
EDIT: When I originally posted this question I thought that IDEA using the Eclipse
compiler also compiled fine, but I was wrong. It turns out that it is possible to get IDEA to fail to compile the above code by selecting the Eclipse
compiler. Still, the question is why there is a discrepancy between eclipse and javac.
The answer to "why is there a discrepancy" is straightforward but perhaps not very satisfactory: because compilers have bugs and are furthermore open to interpretation of a very complex language specification. Determining whether it's a bug in javac or Eclipse is a difficult task; I've seen such discrepancies end up being declared both ways, sometimes as Eclipse compiler bugs, sometimes as javac bugs. That determination, especially when it involves generics and new language features (such as lambdas), can get quite tedious and arcane. For example, look at this one that turned out to be a javac bug but did uncover a related issue in Eclipse's compiler: https://bugs.eclipse.org/bugs/show_bug.cgi?id=456459
The best bet is to report it as an Eclipse bug as I did and see if the Eclipse compiler team can/will track it down.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With