11

I have found a strange behavior when working with generics.

In this class Foo<T>, the strings member doesn't have anything to do with T:

package test;
import java.util.ArrayList;

public class Foo<T> {
    ArrayList<String> strings;

    T getSome() {
        return null;
    }
}

The class is used in main:

package test;

public class Main {

    public static void main() {
        Foo<Integer> intFoo = new Foo<>();
        Integer i = intFoo.getSome();
        String s1 = intFoo.strings.get(0);

        Foo rawFoo = new Foo();
        Object o = rawFoo.getSome();
        String s2 = rawFoo.strings.get(0); // Compilation error on this line
    }
}

The compilation error is "incompatible types. required: String found: Object".

It appears that Java forgets the String type argument to ArrayList when raw type of Foo is used.

My java version is 1.7.0_21

arshajii
  • 127,459
  • 24
  • 238
  • 287
Niklas
  • 161
  • 5
  • 7
    This is completely normal. Raw types are completely raw (all members). Please search for similar questions. โ€“ Ben Schulz Oct 08 '13 at 13:14
  • 2
    Raw types are meant for backward compatibility. From the [java tutorial on raw types](http://docs.oracle.com/javase/tutorial/java/generics/rawTypes.html): "When using raw types, you essentially get pre-generics behavior". The raw type for Foo would not be backward-compatible if it had a generic member (even if it does not depend on T) โ€“ Paolo Falabella Oct 08 '13 at 13:29

1 Answers1

13

Simply put, because rawFoo is raw, its non-static members also become raw.

This is outlined in JLS ยง4.8:

More precisely, a raw type is defined to be one of:

  • The reference type that is formed by taking the name of a generic type declaration without an accompanying type argument list.

  • An array type whose element type is a raw type.

  • A non-static member type of a raw type R that is not inherited from a superclass or superinterface of R.

Note the last bullet.

Community
  • 1
  • 1
arshajii
  • 127,459
  • 24
  • 238
  • 287