从通用类型到相同类型的未经检查的转换

Unchecked cast from generic type to the same type

以下代码在 IntelliJ IDEA 中生成警告 Unchecked cast: 'T' to 'U'

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

这对我来说没有意义,因为 TU 被定义为同一类型。有什么问题?

TU 未定义为同一类型。它们都被定义为 extends A,这意味着 TU 可以是不相关的 类,它们实现了 A 接口。因此演员阵容不安全。

您可以做的唯一安全转换是将类型 TU 的引用转换为类型 A。当然你不需要这样的演员表。您可以简单地将它们分配给 A.

类型的变量

虽然 TU 都扩展了 A,但它们不是同一类型。因此你不能从一个转换到另一个。

考虑:

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

你不能从 D 转换到 E。

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

虽然这是未经检查的,但这实际上是安全的,因为 null 可以转换为任何引用类型而无需 ClassCastException.

但是,编译器在转换时不会考虑非空引用的值:它只是 "some" T。这是一个例子,你,程序员,比编译器更了解类型,因为你知道 t == null,所以你可以通过添加强制转换和 @SuppressWarnings 合法地要求编译器信任你。

但是如果 t 不为空,这并不总是安全的。 TU 是不同的类型:它们是 "something that extends A" 和 "something (maybe the same, maybe not) that extends A"。

为了更具体一点,这里有一个等效的例子:

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

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

这将失败并显示 ClassCastException,因为 Integer 不是 String

如果您不希望它们是不同的类型,请删除其中一个(当然还有强制转换)。

Parent:

interface A {
} 

Child:

class B implements A {

}

class C implements A {

}

在上面的例子中A是parentB和C。

示例:

下面的代码可以正常工作。

  A a = new B();

  B b = (B)a;

这将触发 class 转换异常。

  B b = new B();

  C c = (C) b;

您不能使用 Siblings 类型进行类型转换。这是因为您可能会尝试访问可能出现在结果 class.

中的 methods/properties

String,Integer,Object也是一样。 Object 是 parent
Integer & String 是 child for Object class 但你不能转换这些 classed.