FULL PRODUCT VERSION :
java version "1.5.0_01"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_01-b08)
Java HotSpot(TM) Client VM (build 1.5.0_01-b08, mixed mode)
1.6.0_02-ea-b02
ADDITIONAL OS VERSION INFORMATION :
Linux 2.6.18.5 #1 SMP i686 GNU/Linux
A DESCRIPTION OF THE PROBLEM :
This is a superset of Bug 6468354.
Type inference on assignment often fails if one or more of the type parameters is bounded. For example:
<E extends Comparable<? super E>>
<K extends Comparable<K>, V extends Comparable<V>>
<K extends Comparable<? super K>, V extends Comparable<? super V>>
See the test cases below for more concrete examples.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
See the test case below for concrete examples.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
The test case below should compile without errors. The compiler should be able to infer the correct type based on the assignment.
ACTUAL -
The test case fails to compile. See the error messages below.
ERROR MESSAGES/STACK TRACES THAT OCCUR :
Foo.java:4: incompatible types; no instance(s) of type variable(s) E exist so that Set<E> conforms to Set<java.lang.String>
found : <E>Set<E>
required: Set<java.lang.String>
Set<String> set1 = newSet1(); // fails
^
Foo.java:7: incompatible types; no instance(s) of type variable(s) K,V exist so that Map<K,V> conforms to Map<java.lang.String,java.lang.Integer>
found : <K,V>Map<K,V>
required: Map<java.lang.String,java.lang.Integer>
Map<String, Integer> map1 = newMap1(); // fails
^
Foo.java:8: incompatible types; no instance(s) of type variable(s) K,V exist so that Map<K,V> conforms to Map<java.lang.String,java.lang.Integer>
found : <K,V>Map<K,V>
required: Map<java.lang.String,java.lang.Integer>
Map<String, Integer> map2 = newMap2(); // fails
^
3 errors
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
public class Foo {
public static void main(String[] args) {
Set<String> set1 = newSet1(); // fails
Set<String> set2 = newSet2(); // succeeds
Map<String, Integer> map1 = newMap1(); // fails
Map<String, Integer> map2 = newMap2(); // fails
Map<String, Integer> map3 = newMap3(); // succeeds
}
static <E extends Comparable<? super E>> Set<E> newSet1() {
return new Set<E>();
}
static <E extends Comparable<E>> Set<E> newSet2() {
return new Set<E>();
}
static <K extends Comparable<? super K>, V extends Comparable<? super V>>
Map<K,V> newMap1() {
return new Map<K,V>();
}
static <K extends Comparable<K>, V extends Comparable<V>> Map<K,V> newMap2() {
return new Map<K,V>();
}
static <K extends Comparable<K>, V extends Comparable<?>> Map<K,V> newMap3() {
return new Map<K,V>();
}
}
class Set<E> {}
class Map<K,V> {}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
The test case includes an example work-around, which is to declare the type parameters as:
<K extends Comparable<K>, V extends Comparable<?>>
This is obviously undesirable, as it doesn't fully express the type constraints for a Map that contains self-comparable keys and values. The K parameter is bound too tightly, and the V parameter is bound too loosely!
An even looser work around is:
<K,V>
which simply gives up trying to enforce that the K and V types are comparable.