具有多个接口的Java通用对象

Sim*_*mY4 10 java generics

假设我有一个我使用的泛型类,声明如下:

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

Dol*_*000 3

我确实找到了一种不使用原始类型即可完成您要求的方法,但它仍然涉及一对未经检查的强制转换:

@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)