| Summary: | [Generics] Type mismatch, field's generic type lost when generic type is omitted for the field's class | ||
|---|---|---|---|
| Product: | [Eclipse Project] JDT | Reporter: | Nathan Sweet <misc> |
| Component: | Core | Assignee: | Sasikanth Bharadwaj <sasikanth.bharadwaj> |
| Status: | CLOSED INVALID | QA Contact: | |
| Severity: | normal | ||
| Priority: | P3 | CC: | jarthana, stephan.herrmann |
| Version: | 4.5.1 | ||
| Target Milestone: | 4.6 RC1 | ||
| Hardware: | PC | ||
| OS: | Windows 10 | ||
| Whiteboard: | |||
I believe this is the expected behavior. Javac reports the same error. Sasi, please take this to completion. My apoligies, I seem to have found why it occurs in the spec: https://docs.oracle.com/javase/specs/jls/se8/html/jls-4.html#jls-4.8 "The type of a constructor (§8.8), instance method (§8.4, §9.4), or non-static field (§8.3) of a raw type C that is not inherited from its superclasses or superinterfaces is the raw type that corresponds to the erasure of its type in the generic declaration corresponding to C." I still don't understand why fields of a raw type would also become raw types when their generic types are unrelated to the generic types of the declaring class, but it seems there is no bug here. (In reply to Nathan Sweet from comment #2) > My apoligies, I seem to have found why it occurs in the spec: > https://docs.oracle.com/javase/specs/jls/se8/html/jls-4.html#jls-4.8 > "The type of a constructor (§8.8), instance method (§8.4, §9.4), or > non-static field (§8.3) of a raw type C that is not inherited from its > superclasses or superinterfaces is the raw type that corresponds to the > erasure of its type in the generic declaration corresponding to C." Thanks for digging out the JLS reference. I agree that this explains why the error reported from both compilers is indeed mandated by JLS. > I still don't understand why fields of a raw type would also become raw > types when their generic types are unrelated to the generic types of the > declaring class, but it seems there is no bug here. "Why"-questions regarding JLS are difficult to answer, but I think it has to do with the intention behind introducing raw types in the first place: to allow interfacing new code with pre-java-5 legacy code. It wouldn't be consistent to trust *any* generic type information across this bridge. This also hints at the solution: never use raw types. Never. We're speaking about a "feature" that has been deprecated more than 10 years ago. (In reply to Stephan Herrmann from comment #3) > "Why"-questions regarding JLS are difficult to answer, but I think it has to > do with the intention behind introducing raw types in the first place: to > allow interfacing new code with pre-java-5 legacy code. It wouldn't be > consistent to trust *any* generic type information across this bridge. > > This also hints at the solution: never use raw types. Never. We're speaking > about a "feature" that has been deprecated more than 10 years ago. Very interesting, thanks for the explanation. I tend to use raw types when I mean <?>, simply for brevity. It's nice to know the differences. |
This code fails to compile on the line indicated: public class Test { static public class A<Z> { B<String> array; } static public class B<Y> { public Y get () { return null; } } static public void main (String[] args) throws Exception { A a = new A(); String x = a.array.get(); // Type mismatch: cannot convert from Object to String } } Compilation succeeds if local "a" is declared with any generic type, such as "A<?> a", "A<Object> a", "A<Integer> a", etc. Expected: the generic type of A not to affect the "B<String> array" field.