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

时间:2014-05-24 02:58:16

标签: java generics collections interface casting

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

  • 有一个带有派生接口的接口 A
  • 假设 A 的某个扩展接口名为 B
  • 我们假设有一个 C 类实施 B

我有一个工厂/池类 F ,我想从中获取实例列表(或集合或类似集合)。 我想要的基本上是这样的:

List<B> instances = F.getAllSuitableInstances(parameters);

将我的参数指定的所有实例作为B的集合。

  

首次尝试使用此功能签名

     

public List<A> getAllSuitableInstances(parameters);

     

但是当我尝试将结果列表转换为List以供使用时,我   告诉“不兼容的类型” - 即使B来自A。

     

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

     

public <T> List<T> getAllSuitableInstances(parameters, T);

     

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

我知道我可以使用<?>进行投射,但我希望尽可能使其成为类型安全。

那么,完成这项工作的最佳方式是什么?

2 个答案:

答案 0 :(得分:1)

  

即使B来自A。

你必须要小心--Java的泛型是不变的,这意味着Something<Superclass> Something<Subclass>的超类(例如List<Number> List<Integer>的超类。关于此问题有很多问题,因此我不会重复其他人可以更有效地解释的信息,例如herehere

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

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

应该有效,除非我误解了你的要求。这样做的缺点是T可能任何,因此您可以在类型为T的对象上调用的方法有所限制,但如果您不是这样做就没有必要担心了。

如果你的接口中的方法是必要的,以使你的方法工作(看起来不像,但以防万一),你总是可以添加边界(例如public <T extends A> List<T>...)到你的泛型类型,所以编译器知道方法中T的所有实例都是A类型或A的子类型。

如果您需要在方法中使用T类型(例如instanceof检查),则一个选项是传入Class对象,使用其方法执行运行时等效的instanceof检查和转换(以及其他选项):

public <T> List<T> getAllSuitableInstance(parameters, Class<? extends T> clazz); // Might be able to use just Class<T> too

希望这会有所帮助。如果我对你需要的东西出错了,请告诉我。

答案 1 :(得分:1)

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

当我们有两种具体类型AB时(例如,NumberInteger),MyClass<A>与{{1}无关},无论MyClass<B>A是否相关。

B的共同父母。

无需像第二个选项中提到的那样传递课程

这应该对你有用

MyClass<A> and MyClass<B> is Object