Java - 定义扩展A类并实现接口B的成员

时间:2015-09-18 17:10:36

标签: java object generics interface anonymous-types

我有一个必须满足两个条件的变量,我想在定义中设置它们

我知道我可以使用单个变量定义任一条件,就像在任何这些示例中一样

private Class<? extends A> variable; //or
private A variable; //or
private Class<? extends B> variable; //or
private B variable;

但有没有办法让变量满足这两个条件?

我希望有类似的东西

private Class<? extends A implements B> variable;

但是当我需要调用它或存储多个副本时,我找不到任何方法可以做到这一点

2 个答案:

答案 0 :(得分:2)

您可以声明具有多个边界的类型参数,例如:

public static <T extends A & B> void test(Class<T> clazz)

但是你不能声明一个有多个边界的变量:

private Class<? extends A & B> variable;  // doesn't work

您可以创建扩展abstract并实施C的{​​{1}}类A,以便只需要一个绑定。

B

然后:

abstract class C extends A implements B {}

答案 1 :(得分:1)

虽然Java不直接支持像A&B这样的交集类型,但这些类型确实出现在类型参数边界和捕获转换中。我们可以用一层抽象来表达A&B

public class ValueAB<T extends A&B>
{
    public final T v;

    // constructor ...
}

public class ClassAB<T extends A&B>
{
    public final Class<T> clazz;

    // constructor ...
}

我们使用包装器A&B, Class<? extends A&B>

而不是ValueAB, ClassAB
    ClassAB<?> clazz = new ClassAB<>(Foo.class);   

    ValueAB<?> value = new ValueAB<>(clazz.c.newInstance());

    value.v.methodOfA();
    value.v.methodOfB();

对于As和Bs的每种组合,此解决方案需要包装器。

另一种解决方案是仅使用A作为类型参数绑定; B将由通配符绑定提供。如果您需要在使用站点表达多个A&B1, A&B2, ...类型,这可能会更好。

public class ValueA<T extends A>
{
    public final T v;
    ...
}


public class ClassA<T extends A>
{
    public final Class<T> c;
    ...
}

---

    ClassA<? extends B> clazz = new ClassA<>(Foo.class);

    ValueA<? extends B> value = new ValueA<>(clazz.c.newInstance());

如果在这些情况下令人困惑的通配符如何工作,请参阅我的article on wildcard

第三种解决方案在包装的申报地点没有A或B;使用网站提供A和B.

public class Value<T extends S, S>
{
    public final T v;
    ...
}


public class Clazz<T extends S, S>
{
    public final Class<T> c;
    ...
}

---

    Clazz<? extends A, B> clazz = new Clazz<>(Foo.class);

    Value<? extends A, B> value = new Value<>(clazz.c.newInstance());
然而,这可能太令人困惑了。