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 );
}
}
If we can't eliminate the “unchecked cast” warning and we're sure that the code provoking the warning is typesafe, we can suppress the warning using the SuppressWarnings(“unchecked”) annotation. When we use the @SuppressWarning(“unchecked”) annotation, we should always put it on the smallest scope possible.
We can use the annotation SuppressWarnings(“unchecked”) to suppress the warning.
An unchecked warning tells a programmer that a cast may cause a program to throw an exception somewhere else. Suppressing the warning with @SuppressWarnings("unchecked") tells the compiler that the programmer believes the code to be safe and won't cause unexpected exceptions.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With