为什么Java强制转换泛型类型?
我不明白,当参数化类型被定义为扩展基类时,为什么编译器看不到强制转换是安全的。以下是一些在我看来不必要的类型转换示例。此外,当我包含演员阵容时,我的IDE(IntelliJ IDEA)警告说演员阵容未经检查,好像在暗示我做错了什么。有没有避免这些类型转换和警告的习惯用法?既然声明声明类型扩展了基类,为什么还需要强制转换呢为什么Java强制转换泛型类型?,java,generics,collections,casting,Java,Generics,Collections,Casting,我不明白,当参数化类型被定义为扩展基类时,为什么编译器看不到强制转换是安全的。以下是一些在我看来不必要的类型转换示例。此外,当我包含演员阵容时,我的IDE(IntelliJ IDEA)警告说演员阵容未经检查,好像在暗示我做错了什么。有没有避免这些类型转换和警告的习惯用法?既然声明声明类型扩展了基类,为什么还需要强制转换呢 class Shape {} class Polygon extends Shape {} public class Foo<T extends Shape>
class Shape {}
class Polygon extends Shape {}
public class Foo<T extends Shape>
{
Set<Polygon> polygons;
// Why must this be cast?
Set<T> shapes = (Set<T>) new HashSet<Polygon>();
T getFirst()
{
// Why must this be cast?
return (T) polygons.iterator().next();
}
Iterable<T> getShapes()
{
// Why must this be cast?
return (Iterable<T>) polygons;
}
}
类形状{}
类多边形扩展形状{}
公开课Foo
{
设置多边形;
//为什么要投这个?
Set shapes=(Set)new HashSet();
T getFirst()
{
//为什么要投这个?
返回(T)polygons.iterator().next();
}
Iterable getShapes()
{
//为什么要投这个?
返回(可编辑)多边形;
}
}
在第一个示例中,Set
不是HashSet
的基类
在第二个示例中,
polygons.iterator().next()
的类型是Polygon
,这与TT扩展形状,Polygon扩展形状不同。
所以没有理由T扩展多边形让我们假设您已经像这样实例化了您的类:
Foo<Circle> circleFoo = new Foo<Circle>( );
Foo-circleFoo=new-Foo();
然后,Set
无法安全地分配HashSet
在getFirst
中:您无法将多边形
安全地投射到圆
在getShapes
:您无法安全地将Iterable
转换为Iterable
,您可能有兴趣阅读Java泛型
基本上
Box<Integer> and Box<Double> are not subtypes of Box<Number>
Box和Box不是Box的子类型
设置形状=(设置)新HashSet();
由于T
这里可以是扩展形状的任何对象,并且您试图只适合多边形,因此需要进行强制转换<代码>圆
是一个形状
,但它不是多边形
。最佳实践是将参数化泛型视为唯一类
如果java允许在没有强制转换的情况下执行上述操作,那么它将为向集合添加任何T
打开一扇门。假设您将多边形
集指定给一个集
,然后向其添加圆
对象。这会引发很多运行时问题。//为什么必须强制执行此操作?
// Why must this be cast?
Set<T> shapes = (Set<T>) new HashSet<Polygon>();
Set shapes=(Set)new HashSet();
这是你最小的问题。转换实际上在逻辑上是不正确的<如果a和B是不同的,即使a是B的子类型,代码>集合
也不是集合的子类型。如果我们有可重新定义的泛型,此转换将失败。我一度理解这一点。谢谢你简洁的复习。我现在明白了。此代码仅在使用类型参数Shape
或Polygon
实例化类Foo
时正确。FWIW,我正在使用一个api,其中传入类型为Class
的参数,并在调用clazz.isAssignableFrom(Polygon.Class)
的方法中确定哪些强制转换是安全的。
// Why must this be cast?
Set<T> shapes = (Set<T>) new HashSet<Polygon>();