虽然 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 ...
}
我们使用包装器ValueAB, ClassAB而不是A&B, Class<? extends A&B>
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());
然而这可能太令人困惑了。