FULL PRODUCT VERSION :
java version "1.8.0_74"
Java(TM) SE Runtime Environment (build 1.8.0_74-b02)
Java HotSpot(TM) 64-Bit Server VM (build 25.74-b02, mixed mode)
ADDITIONAL OS VERSION INFORMATION :
Windows 10,
Fedora 22,
A DESCRIPTION OF THE PROBLEM :
When using JDK8 and using -source 1.8 -target 1.8 compiling of code provided below fails to compile with error
"incompatible types: java.lang.Object cannot be converted to T"
If we use -source 1.7 -target 1.7 JDK8 javac compiles the code without problems.
Same code compiles on JDK7
If we use JDK9-ea+107, it also compiles without problems no mater what -source/-target we use.
Simple reproducer can also be found at https://github.com/ctomc/jdk8-compiler
REGRESSION. Last worked in version 7u76
ADDITIONAL REGRESSION INFORMATION:
java version "1.7.0_72"
Java(TM) SE Runtime Environment (build 1.7.0_72-b14)
Java HotSpot(TM) Client VM (build 24.72-b04, mixed mode, sharing)
It also compiles correctly when using JDK9-ea (both jigsaw and normal builds)
java version "9-ea"
Java(TM) SE Runtime Environment (build 9-ea+107-jigsaw-nightly-h4560-20160301)
Java HotSpot(TM) 64-Bit Server VM (build 9-ea+107-jigsaw-nightly-h4560-20160301, mixed mode)
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Use JDK8 with -source 1.8 -target 1.8 and try to compile
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
compile successes
ACTUAL -
compile fails
ERROR MESSAGES/STACK TRACES THAT OCCUR :
Option.java:[12,37] incompatible types: java.lang.Object cannot be converted to T
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
public class Option {
interface ValueParser<T> {
T parseValue(String string, ClassLoader classLoader) throws IllegalArgumentException;
}
static <T> Option.ValueParser<T> getEnumParser(final Class<T> enumType) {
return new ValueParser<T>() {
public T parseValue(final String string, final ClassLoader classLoader) throws IllegalArgumentException {
return enumType.cast(Enum.valueOf(enumType.asSubclass(Enum.class), string.trim()));
}
};
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
Rearrange code and manually cast.
static <T, E extends Enum<E>> Option.ValueParser<T> getEnumParser(final Class<T> enumType) {
return new ValueParser<T>() {
public T parseValue(final String string, final ClassLoader classLoader) throws IllegalArgumentException {
return enumType.cast(Enum.<E>valueOf(asEnum(enumType), string.trim()));
}
};
}
@SuppressWarnings("unchecked")
private static <T, E extends Enum<E>> Class<E> asEnum(final Class<T> enumType) {
return (Class<E>) enumType;
}