Why does javac complain about generics unrelated to the class' type arguments?

648 Views Asked by At

Please read the comments in the code in order, the question details are there.
Why is this difference happening?
Please quote the JLS if possible.

import java.util.*;

/**
 * Suppose I have a generic class
 * @param <T> with a type argument.
 */
class Generic<T> {
    // Apart from using T normally,
    T paramMethod() { return null; }
    // the class' interface also contains Generic Java Collections
    // which are not using T, but unrelated types.
    List<Integer> unrelatedMethod() { return null; }
}

@SuppressWarnings("unused")
public class Test {
    // If I use the class properly (with qualified type arguments)
    void properUsage() {
        Generic<String> g = new Generic<String>();

        // everything works fine.
        String s = g.paramMethod();
        List<Integer> pos = g.unrelatedMethod();

        // OK error: incompatible types: List<String> := List<Integer>
        List<String> thisShouldErrorCompile = g.unrelatedMethod();
    }

    // But when I use the raw type, *ALL* the generics support is gone, even the Collections'.
    void rawUsage() {
        // Using Generic<?> as the type turns fixes the warnings below.
        Generic g = new Generic();

        // OK error: incompatible types: String := Object
        String s = g.paramMethod();

        // WTF warning: unchecked conversion: List<Integer> := raw List
        List<Integer> pos = g.unrelatedMethod();

        // WTF warning: unchecked conversion: List<String> := raw List
        List<String> thisShouldErrorCompile = g.unrelatedMethod();
    }
}

Side note

I originally found this in IntelliJ IDEA, but I guess that compiler is compatible with javac because when I compiled the above code with the following it gave the same errors/warnings.

$ javac -version
javac 1.7.0_05
$ javac Test.java -Xlint:unchecked
...
$ javac Test.java -Xlint:unchecked -source 1.5 -target 1.5
...
1

There are 1 best solutions below

0
On BEST ANSWER

From JLS 4.8 Raw Types

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 generics into the Java programming language is strongly discouraged.

and

The type of a constructor (§8.8), instance method (§8.4, §9.4), or non-static field (§8.3) M 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.

Which - if you read it carefully - implies that all types are erased, not just the type you left out.