简体   繁体   中英

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?

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 .

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.

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.

    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).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM