我有一个必须满足两个条件的变量,我想在定义中设置它们
我知道我可以使用单个变量定义任一条件,就像在任何这些示例中一样
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;
但是当我需要调用它或存储多个副本时,我找不到任何方法可以做到这一点
答案 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());
然而,这可能太令人困惑了。