假设我有一个我使用的泛型类,声明如下:
public class ConfigurableRuleKey<R extends Configurable & Rule> extends Key<R> {
private final R rule
public ConfigurableRuleKey(R rule) {
this.rule = rule;
}
/* Additional methods are declared here */
}
Run Code Online (Sandbox Code Playgroud)
我想实现一个工厂方法,检查传递规则是否实现接口Configurable,创建可配置规则或只创建一个基本密钥:
public static <R extends Rule> Key<R> create(R rule) {
if (rule instanceof Configurable) {
return new ConfigurableRuleKey<>(rule); //This will not compile
} else {
return new RuleKey<>(rule);
}
}
Run Code Online (Sandbox Code Playgroud)
问题是在我的工厂方法中我不能将规则传递给构造函数,ConfigurableRuleKey因为它不符合声明的泛型约束(如果我明确检查它实现的话,则为事件Configurable).问题是如何构建我的规则实例以使其符合构造函数限制ConfigurableRuleKey?
我确实找到了一种不使用原始类型即可完成您要求的方法,但它仍然涉及一对未经检查的强制转换:
@SuppressWarnings("unchecked")
public static <R extends Rule, T extends Rule & Configurable> Key<R> create(R rule) {
if (rule instanceof Configurable) {
return (Key<R>)new ConfigurableRuleKey<>((T)rule);
} else {
return new RuleKey<>(rule);
}
}
Run Code Online (Sandbox Code Playgroud)
我不确定这是否比 sp00m 的答案更好,但至少是不同的。:)
无法在 Java 泛型中正确构造的内在原因似乎是交集类型需要从具体接口构造,而不能从其他类型变量构造。因此,在此示例中无法T以 受 为界的方式进行构造R。如果没有这种能力,甚至没有办法拥有类似于Class.asSubclass抽象这种行为的神奇方法。
编辑:相关地,Java 8 似乎引入了匿名交集类型,您可以在其中转换为多个接口 - 例如。(Configurable & Rule)rule-- 但即使这样也没有帮助,因为与上面相同的原因,你不能转换为(Configurable & R). 然而,摆脱类型变量会有所帮助T:
@SuppressWarnings("unchecked")
public static <R extends Rule> Key<R> create(R rule) {
if (rule instanceof Configurable) {
return (Key<R>)new ConfigurableRuleKey<>((Configurable & Rule)rule);
} else {
return new RuleKey<>(rule);
}
}
Run Code Online (Sandbox Code Playgroud)