Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/365.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
为什么Java强制转换泛型类型?_Java_Generics_Collections_Casting - Fatal编程技术网

为什么Java强制转换泛型类型?

为什么Java强制转换泛型类型?,java,generics,collections,casting,Java,Generics,Collections,Casting,我不明白,当参数化类型被定义为扩展基类时,为什么编译器看不到强制转换是安全的。以下是一些在我看来不必要的类型转换示例。此外,当我包含演员阵容时,我的IDE(IntelliJ IDEA)警告说演员阵容未经检查,好像在暗示我做错了什么。有没有避免这些类型转换和警告的习惯用法?既然声明声明类型扩展了基类,为什么还需要强制转换呢 class Shape {} class Polygon extends Shape {} public class Foo<T extends Shape>

我不明白,当参数化类型被定义为扩展基类时,为什么编译器看不到强制转换是安全的。以下是一些在我看来不必要的类型转换示例。此外,当我包含演员阵容时,我的IDE(IntelliJ IDEA)警告说演员阵容未经检查,好像在暗示我做错了什么。有没有避免这些类型转换和警告的习惯用法?既然声明声明类型扩展了基类,为什么还需要强制转换呢

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
,这与
T

T扩展形状,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>();