假设我有一个通用类,该类声明如下:

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 */

}

我想实现一个工厂方法,该方法可以在创建可配置规则或仅创建基本键时检查通过的规则是否实现了Configurable接口(interface):
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);
    }
}

问题在于,在我的工厂方法中,我无法将规则传递给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);
    }
}

我不确定这是否比sp00m的答案更好,但至少是不同的。 :)

无法在Java的泛型中正确构造它的内在原因似乎是,交集类型需要从具体的接口(interface)构造,而不能从其他类型的变量构造。因此,在此示例中,没有办法以T为界来构造R。如果没有该功能,甚至没有办法像Class.asSubclass一样抽象这种行为的魔术方法。

编辑:相关地,似乎Java 8引入了匿名交集类型,您可以在其中转换为多个接口(interface),例如。 (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);
    }
}

10-04 20:34