Nickkk
Nickkk

Reputation: 2647

Unchecked cast from generic type to the same type

The following code generates a warning Unchecked cast: 'T' to 'U' in IntelliJ IDEA:

interface A {}
class B<T extends A, U extends A> {
    void f() {
        final T t = null;
        final U u = (U) t;
    }
}

This doesn't make sense to me, since T and U are defined as the same type. What is the problem?

Upvotes: 2

Views: 1022

Answers (4)

GnanaJeyam
GnanaJeyam

Reputation: 3170

Parent:

interface A {
} 

Child:

class B implements A {

}

class C implements A {

}

In the above example A is parent B and C.

Example:

The below code will works fine.

  A a = new B();

  B b = (B)a;

This will trigger class Cast Exception.

  B b = new B();

  C c = (C) b;

You can't type cast with your Siblings type. This is because You may try to access the methods/properties that may present in the resultant class.

Same thing can be to String,Integer,Object. Object is parent
Integer & String are the child for Object class but you cannot cast these classed.

Upvotes: 1

Andy Turner
Andy Turner

Reputation: 140309

    final T t = null;
    final U u = (U) t;

Although this is unchecked, this is actually safe, because null can be cast to any reference type without a ClassCastException.

However, the compiler doesn't consider the value of a non-null reference when you cast it: it's simply "some" T. This is an example of where you, the programmer, know more about the types than the compiler, because you know that t == null, so you can legitimately ask the compiler to trust you by adding casts and @SuppressWarnings.

But if t were non-null, this wouldn't always be safe. T and U are different types: they are "something that extends A" and "something (maybe the same, maybe not) that extends A".

To make this a little bit more concrete, here's an equivalent example:

class B<T extends Serializable, U extends Serializable> {
  U method(T t) {
    return (U) t;
  }
}

String s = new B<Integer, String>().method(1);

This will fail with a ClassCastException, because an Integer isn't a String.

If you don't want them to be different types, remove one of them (and, of course, the cast).

Upvotes: 0

dave
dave

Reputation: 11975

While both T and U extend A, they are not the same type. Hence you cannot cast from one to the other.

Consider:

class D implements A {}
class E implements A {}
B<D, E> b;

You cannot cast from D to E.

Upvotes: 1

Eran
Eran

Reputation: 393781

T and U are not defined as the same type. They are both defined as extends A, which means T and U can be unrelated classes that implement the A interface. Hence the cast is not safe.

The only safe cast you can do is to cast references of type T or U to type A. Of course you don't need such a cast. You can simply assign them to a variable of type A.

Upvotes: 5

Related Questions