First, a little background (or skip down a little if not interested). I'm irritated and confused! This should be a pretty simple use case, and indeed my code has been compiling just fine with the Eclipse JDT compiler, so until now I've been configuring Maven to make sure to do this. It's been bothering me too much though that it doesn't compile with the Oracle JDK and OpenJDK, as I thought it may actually have been a problem with my code, so I've looked into it again.
I thought perhaps that the bug was in the JDT compiler for allowing it to compile, not the Oracle JDK and OpenJDK for not allowing it, both of which I've also tested this with. The original code in question was considerably more complicated, so it was much more difficult for me to see where the problem was, and in fact I was very surprised to see the extent to which this could be reduced whilst still not compiling.
Either the Eclipse JDT compiler or the Oracle JDK and OpenJDK have a pretty major (imho) bug.
TL;DR
This is a fairly minimal representation of the code in question. (The type bound of Anything can be replaced by any interface and the compiler behaviour won't change):
public class Bug<X extends Property<?, ?> & Anything> {
}
interface Property<C, S extends C> extends PropertyConst<C> {
@Override
public S get();
}
interface PropertyConst<C> {
public C get();
}
interface Anything {
}
To summarise, I think this should compile just fine, but the Oracle JDK 7 & 8 and OpenJDK 7 disagree. It does compile for me using Eclipse Juno.
When compiled with either of those compilers the code above gives something like the following error, but works just fine with the JDT compiler:
Bug.java:3: error: types PropertyConst<?> and Property<?,?> are incompatible; both define get(), but with unrelated return types
public class Bug<X extends Property<?, ?> & Anything> {
^
1 error
This makes no sense. The return types are obviously related because one of the two methods referenced necessarily frickin' overrides the other. I'm pretty much 99% confident that this should work, in fact the only reason that last 1% is missing is that it's just too basic a use of generics for this to not have been spotted, and yet I found no bug report relating to it. (Admittedly I didn't look to hard because http://bugs.sun.com/ is just the worst. Can you even filter keyword search results by whether a bug report is still open? Ugh.)
The most confusing part for me is that it compiles just fine when you remove the type bounding for Anything on X, even though the extra interface has nothing to do with the error.
Can anybody put my mind at rest? Anyone know of a bug report which exists for this, or has had experience with it before and can tell me what the problem is? If I don't get any conclusive answers I'll file some bug reports.
Edit:
A couple of people have pointed out that I had a forward reference error with <S extends C, C>. Don't know why I wasn't getting this error, it even compiled in Eclipse with the JDT...
Anyway, it still doesn't compile for me with OpenJDK 7 or Oracle JDK 7 / 8, so I modified the question to remove the issue.
Edit 2:
A quick check confirms that this sort of forward reference is now legal in Java 7. As it should be!
Edit 3:
I've posted bug reports on http://bugs.sun.com/. I'll post links here if/when they're accepted.
Anything
interface ? – Rondure