繁体   English   中英

Java通用方法可选类型

[英]Java generic method optional type

我在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指定类型,而在其他情况下(例如:当方法调用用两种MyClass类型填充ArrayList时)都可以省去该类型?

但是,将同时容纳两种类型的MyClass的ArrayList将容纳MyClass<A>对象和MyClass<B>对象(而不是MyClass<superclass>对象)

同时包含MyClass<A>MyClass<B>应具有以下类型:

List<MyClass<? extends C>>

然后,您可以将MyClass<A>MyClass<B>元素添加到列表中。


如果您需要您的方法在不同的时间返回不同的类型,则它必须以某种方式取决于该方法的参数。 因此,例如,如果methodOne()MyClass实例作为参数,则可以定义这样的方法(请注意<T>声明,使之成为通用方法 ):

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, ...);

您更喜欢哪种选择取决于您的用例。

您必须使用此方法签名:

<T extends C> ArrayList<MyClass<? extends T>> methodOne(int param1)

这将返回C及其子类的MyClass对象列表。

像这样使用它:

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;
    }
}

您不能这样做,因为即使class A扩展了class BList<A>也不扩展List<B> 这是因为A对象支持具有相同签名的B所有属性和方法。

但是List<B>有一个接受B对象的add方法,其中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));

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM