Reputation: 29139
Can anyone explain why there is an untyped conversion warning on y assignment line? Note that there is no warning on either x or z assignments.
public class Entity<T>
{
@SuppressWarnings("unchecked")
public <TX> Entity<TX> typed( Class<TX> type )
{
return (Entity<TX>) this;
}
@SuppressWarnings("unchecked")
public static <TX> Entity<TX> typed( Entity<?> entity, Class<TX> type )
{
return (Entity<TX>) entity;
}
public static void main( final String[] args )
{
final Entity<?> a = new Entity<Integer>();
final Entity b = (Entity) a;
final Entity<Integer> x = a.typed( Integer.class );
final Entity<Integer> y = b.typed( Integer.class );
final Entity<Integer> z = typed( b, Integer.class );
}
}
Upvotes: 8
Views: 162
Reputation: 51030
From the declaration:
final Entity<?> a = new Entity<Integer>();
a
is typed, so the method call is a.typed( Integer.class )
is also typed.
In typed( b, Integer.class )
it works because the method is generic.
But in
final Entity b = (Entity) a;
you have turned-off generics (for b
by using the raw-type instead of the generic-version of Entity
) so the invocation b.typed( Integer.class )
is untyped. So you get the warning.
Upvotes: 1
Reputation: 35453
You are "downcasting" a, removing it's type identifier when assigning to b. Because b is now untyped, you are getting an untyped conversion warning because it no longer knows the type.
Upvotes: 0
Reputation: 1500913
b
is of type Entity
, which is a raw type. Therefore its API looks like this:
public Entity typed(Class type)
So you're converting from Entity
to Entity<Integer>
. The compiler has lost any correlation between the type
parameter and the kind of entity returned, so it can't do any checking.
To put it another way, you could use:
final Entity<Integer> y = b.typed(String.class);
... and still receive only the same warning. If you try the same change with x
or z
, you'll get a compile-time error instead.
EDIT: As noted in comments, the fact that you're using a raw type removes all traces of generics.
From JLS section 4.8:
To facilitate interfacing with non-generic legacy code, it is possible to use as a type the erasure (§4.6) of a parameterized type (§4.5) or the erasure of an array type (§10.1) whose element type is a parameterized type. Such a type is called a raw type.
And then in section 4.6:
Type erasure also maps the signature (§8.4.2) of a constructor or method to a signature that has no parameterized types or type variables. The erasure of a constructor or method signature s is a signature consisting of the same name as s and the erasures of all the formal parameter types given in s.
Upvotes: 6