raw types warnings and instanceof
Maurizio Cimadamore
Maurizio.Cimadamore at Sun.COM
Mon Nov 3 02:40:42 PST 2008
Martin Buchholz wrote:
> Hi javac maintainers,
>
> This is a bug report, sort of.
>
> Thanks for adding the raw types warnings, but...
>
> they currently warn about
> x instanceof RAW-TYPE
> when they probably should not.
> It is very common to do
>
> void f (Foo<T> x) {
> if (x instanceof Bar) {
> Bar<T> y = (Bar<T>) x;
> ....
>
> The workaround is to do:
>
> void f (Foo<T> x) {
> if (x instanceof Bar<?>) {
> Bar<T> y = (Bar<T>) x;
> ....
>
> but the addition of <?> adds noise without providing any safety.
>
Hi Martin,
thanks for the report on raw warnings (both ones) - frankly, I have to
admit that I'm quite happy with the current design of the raw-type
warnings - I mean, we could disable them for instanceof, add extra-cases
for class literals and so forth, but I don't think that it would be a
viable solution in the long-term. My point is that "it's very common to
do so" does not always imply that "it's right to do so", and I'll try to
show you why. On the other hand we should try not to generate
unavoidable warnings, that is warning that cannot be eliminated (as in
your second example) - in those cases @SuppressWarnings works quite well
as a temporary workaround but I understand that you'd like javac to do
something better (even if other compilers generate similar warnings
under similar circumstances).
The first observation is that JLS already makes it very clear that
raw-types should be avoided whenever possible (quoting from JLS 4.9: "
The use of raw types is allowed only as a concession to compatibility of
legacy code. The use of raw types in code written after the introduction
of genericity into the Java programming language is strongly
discouraged. *It is possible that future versions of the Java
programming language will disallow the use of raw types***") - and the
instanceof example is exactly one of those cases. It's true that adding
a <?> does not provide any extra-kind of type-safety - but it's also
true that List<?> (where List is a generic type) should be preferred to
List, because that's the language - you can think of List as a special
(very special) thing that should be used only when no other JDK 5
compliant option is available (mainly for migration/backward
compatibility issues).
The second point is that we have a very good reason for promoting code
without raw-types in that raw-types pose serious limits when considering
language extensions such as reification. I've been working on
reification for many years and I can assure you that refication would be
here already if it weren't for some corner case regarding - guess who?
raw types - essentially code with raw-types cannot be reified in a
backward-compatible way. Consider the following fragment:
List l = new ArrayList(...);
List<String> ls = (List<String>)l; //ok w/o reification, CCE w/ reification
The third observation is more pragmatic and has to do with a work that
we've recently done in order to make langtools 100% 'raw type warnings
free'. During that cleanup we've been able to detect many bad usages of
generic types - e.g. we were using unparameterized method arguments
(e.g. List) where the following code was assuming that the container was
always carrying a particular type of object (so that we could replace
the argument type with some List<T>). This, in turn, enabled other
optimizations, such as the elimination of some redundant casts, and so
forth. From our perspective raw-types warnings have been quite useful,
as they helped us to improve the quality of our code; I'll give you some
numbers: we had some 149 raw-type warnings in langtools and we recently
managed to remove all of them (but 2). Only 2 out of 149 warnings
couldn't be suppressed because of type-system issues involving generic
types - mostly similar to the one you have described in your second
report - but we could use @SuppressWarnings for those tricky ones.
Hope this helps
Maurizio
> Martin
>
More information about the compiler-dev
mailing list