从通用类型到相同类型的未经检查的转换
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;
}
}
这对我来说没有意义,因为 T
和 U
被定义为同一类型。有什么问题?
T
和 U
未定义为同一类型。它们都被定义为 extends A
,这意味着 T
和 U
可以是不相关的 类,它们实现了 A
接口。因此演员阵容不安全。
您可以做的唯一安全转换是将类型 T
或 U
的引用转换为类型 A
。当然你不需要这样的演员表。您可以简单地将它们分配给 A
.
类型的变量
虽然 T
和 U
都扩展了 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
不为空,这并不总是安全的。 T
和 U
是不同的类型:它们是 "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.
以下代码在 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;
}
}
这对我来说没有意义,因为 T
和 U
被定义为同一类型。有什么问题?
T
和 U
未定义为同一类型。它们都被定义为 extends A
,这意味着 T
和 U
可以是不相关的 类,它们实现了 A
接口。因此演员阵容不安全。
您可以做的唯一安全转换是将类型 T
或 U
的引用转换为类型 A
。当然你不需要这样的演员表。您可以简单地将它们分配给 A
.
虽然 T
和 U
都扩展了 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
不为空,这并不总是安全的。 T
和 U
是不同的类型:它们是 "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/propertiesString,Integer,Object也是一样。 Object 是 parent
Integer & String 是 child for Object class 但你不能转换这些 classed.