Kgalkin
Kgalkin

Reputation: 29

Generic example not compiling?

Having following example:

public class A<S> {
  public S id;
}

public class B extends A<String> {
  B(){
    this.id = "";
  }
}

public class C<K> extends B {
  public K property;

  public static void main(String[] args) {
    System.out.println(new C().id.substring(0,1));
  }
}

new C().id.substring(0,1) would not compile because id is of type Object it says.

Whats wrong and is there a way to do this without casting ?

Upvotes: 1

Views: 88

Answers (1)

Andy Turner
Andy Turner

Reputation: 140318

The relevant section of the language spec for raw types is JLS Sec 4.8 is:

Specifically:

The superclasses (respectively, superinterfaces) of a raw type are the erasures of the superclasses (superinterfaces) of any of the parameterizations of the generic type.

So, the superclasses of raw C are B and raw A, even though the superclass of B is A<String>. (This makes my head hurt somewhat).

The next paragraph says:

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.

So, the type of the id field is the erasure of S, i.e. Object.

As ever, the fix here is don't use raw types.

System.out.println(new C<>().id.trim());
                     // ^^ Can use any relevant type here, but diamond operator works too

Upvotes: 3

Related Questions