我在Java中有一个泛型方法:
public static <T extends C> ArrayList<<MyClass<T>> methodOne(parameter1)
目前,我使用此方法获取特定类型MyClass的ArrayList,如下所示(A和B是C的子类):
ArrayList<MyClass<A>> result = methodOne<A>(param1);
或
ArrayList<MyClass<B>> result = methodOne<B>(param1);
现在我有另一个需要,它适用于包含两种类型的MyClass的ArrayList:
ArrayList<MyClass> result = methodOne<MyClass>(param1);
但是,我无法从methodOne返回ArrayList<MyClass>
,因为它声明它返回ArrayList<MyClass<T>>
对象。
我可以通过将methodOne更改为非泛型来解决此问题:
pubic static ArrayList<MyClass> methodOne(parameter1)
然而,当我可以指定MyClass的类型时,我感觉更安全。如果我使用上述声明,那么我将无法执行以下操作:
ArrayList<MyClass<A>> result = methodOne<A>(param1);
有什么方法可以保留当前的泛型方法,并且能够在我想要的时候为MyClass指定一个类型,并且能够在其他情况下省略该类型(即:当方法调用用两种类型填充ArrayList时of MyClass)?
答案 0 :(得分:1)
但是,将保存两种类型的MyClass的ArrayList将保留
MyClass<A>
个对象和MyClass<B>
个对象(不是MyClass<superclass>
个对象)
同时包含MyClass<A>
和MyClass<B>
的列表应具有以下类型:
List<MyClass<? extends C>>
然后,您可以将MyClass<A>
和MyClass<B>
元素添加到列表中。
如果您需要在不同时间返回不同类型的方法,则必须以某种方式依赖于方法的参数。例如,如果methodOne()
将MyClass
实例作为参数,则可以定义这样的方法(注意<T>
声明,使其成为generic method):< / p>
public <T> List<MyClass<T>> methodOne(MyClass<T> param, ...)
然后你可以让methodOne()
返回与传递的对象相同类型的列表:
List<MyClass<A>> result1 = methodOne(instanceOfA, ...);
List<MyClass<C>> result = methodOne((MyClass<C>)instanceOfA, ...);
如果您不打算传入所需类型的实例,您仍然可以通过传入该类型的Class
来逃避它,如下所示:
public <T> List<MyClass<T>> methodOne(Class<T> clazz, ...)
并致电:
List<MyClass<A>> result1 = methodOne(A.class, ...);
List<MyClass<C>> result = methodOne(C.class, ...);
您更喜欢哪种替代方案取决于您的使用案例。
答案 1 :(得分:1)
您必须使用此方法签名:
<T extends C> ArrayList<MyClass<? extends T>> methodOne(int param1)
将返回MyClass
的列表 - C
及其子类的对象。
像这样使用:
ArrayList<MyClass<? extends C>> resultC = methodOne(123);
resultC.add(new MyClass<A>());
resultC.add(new MyClass<B>());
完整的示例代码:
import java.util.ArrayList;
interface C {}
class A implements C {}
class B implements C {}
class MyClass<X> {}
public class Generic {
public static void main(String[] args) {
ArrayList<MyClass<? extends A>> resultA = methodOne(123);
resultA.add(new MyClass<A>());
ArrayList<MyClass<? extends B>> resultB = methodOne(123);
resultB.add(new MyClass<B>());
ArrayList<MyClass<? extends C>> resultC = methodOne(123);
resultC.add(new MyClass<A>());
resultC.add(new MyClass<B>());
}
static <T extends C> ArrayList<MyClass<? extends T>> methodOne(int param1) {
return null;
}
}
答案 2 :(得分:0)
您不能这样做,因为即使class A
延伸class B
,List<A>
也不会延伸List<B>
。这是因为A
对象支持具有相同签名的B
的所有属性和方法。
但是List<B>
有一个add
方法接受B
个对象,其中List<A>
只接受A
元素。
但是addAll
方法有一个很好的签名(对于List<E>
):
boolean addAll(Collection<? extends E> c)
所以如果可以接受,你可以这样做:
ArrayList<MyClass<? extends abstractAncestor>> l = new ArrayList<MyClass<? extends abstractAncestor>>();
l.addAll(method1<MyClass<A>>(param1));
l.addAll(method1<MyClass<B>>(param1));