Relates :
|
|
Relates :
|
|
Relates :
|
|
Relates :
|
FULL PRODUCT VERSION : java version "1.6.0_10" Java(TM) SE Runtime Environment (build 1.6.0_10-b33) Java HotSpot(TM) Client VM (build 11.0-b15, mixed mode, sharing) ADDITIONAL OS VERSION INFORMATION : Microsoft Windows XP [Version 5.1.2600] (this is not an OS specific issue) EXTRA RELEVANT SYSTEM CONFIGURATION : n/a (this is not a configuration specific issue) A DESCRIPTION OF THE PROBLEM : If a class that has optional generic types is instantiated using the raw type... all return types for methods throughout that class are stripped, and now return raw types. Related bugs: 5073043 5074427 6545698 The problem is not as simple as the solution addressed in these discarded bugs. The problem is one of passivity. If a class has a method with a typesafe construct in the return type, no generic type can EVER add to that class, for it will be break any consumers of that existing method that rely on the typesafety. This seems like a pretty large burden to put on developers. STEPS TO FOLLOW TO REPRODUCE THE PROBLEM : 1. Create a basic class. 2. Create a method within that class that returns a parametrized generic type. (e.g. Collection<String>) 3. Use that method in a way that depends on that return type. (e.g. String s = col.get(0)) 4. Verify everything compiles. 5. Add a generic to the basic class declaration. (e.g. <T>) 6. A compiler error is now generated on the line of code from step 3. EXPECTED VERSUS ACTUAL BEHAVIOR : EXPECTED - I would not expect a raw type returned from a method that does not depend on the class' generic type. (i.e. Obviously a method returning type T would be stripped, but if it's returning an explicit type, there is no reason to strip it.) ACTUAL - Class does not compile. ERROR MESSAGES/STACK TRACES THAT OCCUR : GenericsBug.java:28: incompatible types found : java.lang.Object required: java.lang.Number Number n2 = new Generic().getGenericNumbers().get(0); ^ 1 error REPRODUCIBILITY : This bug can be reproduced always. ---------- BEGIN SOURCE ---------- import java.util.*; public class GenericsBug { public static void main(String[] args) { //Simple class without generics that has a method that returns a type-safe list class NoGeneric { public List<Number> getGenericNumbers() { return new ArrayList<Number>(); } } //This compiles fine, as the typesafe list returns a Number Number n1 = new NoGeneric().getGenericNumbers().get(0); //Simple class with a generic type that has the EXACT SAME method as above that returns a type-safe list class Generic<T> { public List<Number> getGenericNumbers() { return new ArrayList<Number>(); } } //This does not compile, because getGenericNumbers() is now returning a raw List, //simply because the generic not being declared with a type Number n2 = new Generic().getGenericNumbers().get(0); //This DOES compile, because types are not stripped //This is the recommended solution from previous bugs, but we can't //break existing consumers of our class, meaning we can't add generics at all Number n3 = new Generic<Object>().getGenericNumbers().get(0); } } ---------- END SOURCE ---------- CUSTOMER SUBMITTED WORKAROUND : The only workaround is not exposing typesafe objects as return types, and forcing the consumers to infer the cast (effectively preventing the use of generics all together) until we can declare that the class will never have a generic type. For classes and packages without unknown consumers, simply adding the unchecked 'cast' resolves the compiler error. e.g. Number n2 = ((List<Number>)new Generic().getGenericNumbers()).get(0);
|