Take the 2-minute tour ×

I'm just curious what's the generated inferred T type when passing a raw to a T type. It does compile but with a warning.

public class GenericMethodInference {

    static <T> void test5(List<T t>){} // clause (5)

    public static void main(String [] args) {

    List e = new ArrayList<Integer>();
    test5(e);  // clause (6) // ok but with warning.

share|improve this question
add comment

5 Answers

up vote 2 down vote accepted

Assigning a raw type to a generic type will assume no generic constraint (which will default to Object) but remove any compile-time type safety guarantees that might otherwise have existed.

But you cannot assign a raw to a List <Object> since it has been erased

It sounds like there is a fundamental misunderstanding of type erasure here. The raw type is the end result of a generic type. You specified List<Integer>, the compiler verifies against that type information and then removes the <Integer> portion of that, inserting casts to Integer as appropriate from actions against the raw type of List.

That means that these two retrieval operations are exactly the same.

List<Integer> integerList = new ArrayList<Integer>();

Integer i = integerList.get(0); 
Integer ii = (Integer)((List)integerList).get(0);

For example, the following is legal. This only gives a warning (instead of causing a compiler error or runtime error) because we're acting on Object and are still within the appropriate bounds of the contained type.

List<Object> objects = (List)integerList;
Object value = objects.get(0);

It will print out 5. Where the type system helps is if you try to do something like this.

List<String> badStringList = integerList;

It will give you a compiler error stating that there is a type mismatch. Using the raw type directly, however, will throw all of that type safety away and rely solely on your judgement for the correct types that should be used. This allows you to easily shoot yourself in the foot if you get it wrong.

List<String> badStringList = (List)integerList;
String badValue = badStringList.get(0); //ClassCastException is thrown at runtime
share|improve this answer
List<Object> objects = (List)integerList; Why does this gives a warning? This is where my confusion is. I can understand the warning if it is List<String> objects = (List)integerList; or even List<Integer> objects = (List)integerList; But Object is the highest superclass here. So i'm a bit confused –  yapkm01 Sep 29 '11 at 15:17
It gives a warning because you are casting a generic type (which has additional compile-time type information) to a raw type (which has none). It's legal (and has to be for legacy reasons, as irreputable said) but it's not advised. You are essentially saying to the compiler, "You know that List you were managing type changes on? Don't worry about that anymore, I'll do that myself" which produces a warning as the compiler says "Hey, do you realize you're doing this? You could screw this up pretty badly". –  Chris Hannon Sep 29 '11 at 15:33
Thanks for your reply. I don't have any problem with the warning from a generic type to raw type. It is the assignment from the raw back to List <Object> which gives a warning that confuses me. Look at the comment i put on irreputable section –  yapkm01 Sep 29 '11 at 15:35
The same also applies the other way. By taking a raw type and imposing generic information on it, the compiler has no way of verifying that the type conversion is correct and gives you a warning. The conversion is 'unchecked' in that sense. You can suppress that warning if you're absolutely sure that what you're doing is correct and you don't want the compiler to complain, but it's another way of the compiler saying "Hey, you might be about to do something you'll regret". –  Chris Hannon Sep 29 '11 at 17:10
For example, if we split out the conversion in my last example, you will get a warning on List rawList = integerList; because you're removing generic information and an error on List<String> badStringList = rawList; because the compiler cannot verify that your conversion is correct (and in this case, it most certainly is not). –  Chris Hannon Sep 29 '11 at 17:14
show 1 more comment

This is done for backward compatibility. Before generics,

static void test5(List t){}

List e = ...;

When generics was introduced, they need to generify List and methods like test5(), without asking all usages like test5(e) to be rewritten and recompiled. So test5(e) must still be valid.

This is achieved by relaxing type inference rules and method signature matching rules.

Inference: List << List<T> this can't hold in the subtyping sense; however inference rules just ignore it; T has no constraints, and simply picked to be Object

Method signature: List e is is not subtype of the method parameter type List<Object>, however it is acceptable by "method invocation conversion", which allows "unchecked conversion" from List to List<Whatever>; the "unchecked conversion" triggers the mandatory compiler warning.

This is only of historical interest; no programmer today should care. Since obviously there's no way for List to be a subtype of List<T> whatever T is, we should practically treat it as error, and never write code like that (even though it compiles). A List<?> e would work.

share|improve this answer
I wish i could also check yours as an answer. How do i check more than 1 response as an answer? –  yapkm01 Sep 29 '11 at 17:33
add comment

I would say that the inferred type would be Object

share|improve this answer
But you cannot assign a raw to a List <Object> since it has been erased. –  yapkm01 Sep 29 '11 at 3:56
add comment
    public class GenericMethodInference {

    static <T> void test5(List<T> xx) {
        System.out.println(xx.getClass());  //class java.util.ArrayList
        System.out.println(xx.get(0).getClass()); //class java.lang.Integer
        System.out.println(xx.get(1).getClass()); //class java.lang.String
    } // clause (5)

    public static void main(String[] args) {

        List e = new ArrayList<Long>();

This confirms that the type inferred is Object type.

share|improve this answer
How does this show type inferred is Object? Sorry just couldn't see it .. –  yapkm01 Sep 29 '11 at 14:09
add comment

T is a generic one. It can accept any object.

share|improve this answer
add comment

Your Answer


