Java泛型方法可选类型

时间:2015-07-09 13:31:44

标签: java generics

我在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)?

3 个答案:

答案 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 BList<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));