强制转换派生Java接口(泛型)的集合

强制转换派生Java接口(泛型)的集合,java,generics,collections,interface,casting,Java,Generics,Collections,Interface,Casting,制作一个供内部使用的API,我需要一些Java抽象,但我不知道怎么做 存在一个带有派生接口的接口A 假设A的一个扩展接口称为B 假设有一个类C实现了B 我有一个Factory/Pool类F,我想从中获取实例列表(或集合或类似集合)。 我想要的基本上是: List<B> instances = F.getAllSuitableInstances(parameters); List instances=F.getAllSuitableInstances(参数); 将我的参数指定的

制作一个供内部使用的API,我需要一些Java抽象,但我不知道怎么做

  • 存在一个带有派生接口的接口A
  • 假设A的一个扩展接口称为B
  • 假设有一个类C实现了B
我有一个Factory/Pool类F,我想从中获取实例列表(或集合或类似集合)。 我想要的基本上是:

List<B> instances = F.getAllSuitableInstances(parameters);
List instances=F.getAllSuitableInstances(参数);
将我的参数指定的所有实例作为B的集合获取

第一次尝试是使用此函数签名

公共列表getAllSuitableInstances(参数)

但当我试图将结果列表转换为一个列表以供使用时,我 被告知“不兼容类型”-即使B是从A派生的

所以我尝试了java库的功能:

公共列表getAllSuitableInstances(参数,T)

试着用B作为第二个参数调用它。但这不起作用 或者,因为出于某种原因,T必须作为实例提供,并且 接口不能有实例

我知道我可以将
与casting结合使用,但我希望尽可能做到类型安全

那么,实现这一目标的(最佳)方法是什么

即使B是从A派生出来的

这里您必须小心——Java的泛型是不变的,这意味着
某物
某物
的超类(例如
列表
列表
的超类)。关于这一点有很多问题,所以我不会重复其他人可以更有效解释的信息,比如和

至于你的第二个签名,在我看来,
(参数,T)
中的
T
是不必要的

public <T> List<T> getAllSuitableInstance(parameters);

希望这能有所帮助。如果我对您需要的东西有错误,请告诉我。

在使用泛型编程时,这是一个常见的误解,但这是一个需要学习的重要概念

当我们有两种具体类型
A
B
(例如,
Number
Integer
)时,
MyClass
MyClass
没有关系,无论
A
B
是否相关

MyClass和MyClass的共同父对象是Object

甚至不需要通过第二个选项中提到的课程

这应该对你有用

public <T> List<T> getAllSuitableInstances(parameters) {
List<T> list = new ArrayList<>();
 //content add to list
    return list;
}
公共列表getAllSuitableInstances(参数){
列表=新的ArrayList();
//内容添加到列表
退货清单;
}

就这样了,谢谢-带有边界的版本给了我一些类型安全性,同时允许所需的灵活性。您的链接为这个答案增加了价值,使它对其他读者也更有用,所以我更喜欢(并接受)这个答案。@foo没问题!只是一个(可能是多余的)注意事项——带有
的版本主要用于方法内部的工作。如果您只使用普通的
T
,我相信编译器将能够计算出
T->B
,但是在方法内部进行工作可能会有点棘手,因为您完全不知道
T
是什么(除非它是您的一个参数的一部分,比如在带有
类的版本中).你是对的-上面提到的问题的答案也回答我的问题。但我没有找到其他问题,因为我没有寻找它的关键词(狗、动物、多态性)。也许其他人会像我一样表达他们的搜索,所以这个问题的存在可能对某些人仍然有用。
public <T> List<T> getAllSuitableInstances(parameters) {
List<T> list = new ArrayList<>();
 //content add to list
    return list;
}