【问题标题】:Java 8 lists containing generics of mixed (but inheritance-related) typesJava 8 列表包含混合(但与继承相关)类型的泛型
【发布时间】:2021-06-15 14:46:56
【问题描述】:

这里是 Java 8,看到关于泛型的莫名编译器错误。

我有RunnableRule:

public interface RunnableRule<INPUT,OUTPUT> {
    OUTPUT execute(INPUT input, OUTPUT previousOutput);
}

然后AbstractRuleRunner

public abstract class AbstractBaseRuleRunner<INPUT,OUTPUT> {

    private List<RunnableRule<INPUT,OUTPUT>> rules;

    public AbstractBaseRuleRunner(List<RunnableRule<INPUT, OUTPUT>> rules) {
        this.rules = rules;
    }

    protected abstract OUTPUT initOutput();

    public OUTPUT runRules(INPUT input) {

        OUTPUT output = null;
        for (RunnableRule<INPUT,OUTPUT> rule : rules) {

            if (output == null) {
                output = initOutput();
            }

            output = rule.execute(input, output);

        }

        return output;

    }


}

然后是一些豆子:

public interface HasPlaintextPassword {
    String getPlaintextPassword();
}

@Data
public class SignUpRequest implements HasPlaintextPassword {

    @NotNull
    private String email;

    @NotNull
    private String password;

    @NotNull
    private String appRefId;

    private boolean ackTerms;

    @Override
    public String getPlaintextPassword() {
        return getPassword();
    }

}

最后是我的规则运行器的具体实现:

public class SignUpValidationRulesRunner extends AbstractBaseRuleRunner<HasPlaintextPassword, ValidationReport> {

    public SignUpValidationRulesRunner(List<RunnableRule<HasPlaintextPassword, ValidationReport>> runnableRules) {
        super(runnableRules);
    }

    @Override
    protected ValidationReport initOutput() {
        return new ValidationReport();
    }

}

具体的可运行规则:

public class AcksTermsSignUpRule implements RunnableRule<SignUpRequest, ValidationReport>, RuleConstants {

    @Override
    public ValidationReport execute(SignUpRequest signUpRequest, ValidationReport previousOutput) {

        if (!signUpRequest.isAckTerms()) {
            previousOutput.getErrors().add(MUST_ACK_TERMS_ERROR);
        }

        return previousOutput;

    }

}

有些规则会接受SignupRequest 作为输入,因为它们需要使用SignUpRequest 上的某些属性,而有些规则只需要接受HasPlaintextPassword 作为输入,因为它们只是检查密码属性。

最后用胶水把它们粘在一起:

List<RunnableRule<HasPlaintextPassword, ValidationReport>> signUpValidationRules = new ArrayList<>();
AcksTermsSignUpRule acksTermsSignUpRule = new AcksTermsSignUpRule();

signUpValidationRules.add(acksTermsSignUpRule);

这里我在signUpValidationRules.add(acksTermsSignUpRule) 上收到一个编译器错误,指出所需的类型是RunnableRule,但只提供了AcksTermsSignUpRule

我该怎么做才能让我的规则列表接受HasPlaintextPasswordSignUpRequest 作为输入通用参数?因为我需要在同一个列表中组合任一输入类型的规则。

【问题讨论】:

  • 尝试搜索通配符和? extends A? super A 语法

标签: java generics java-8


【解决方案1】:

在这种情况下,您可以使用&lt;? super RunnableRule&lt;?,?&gt;&gt;

 List<? super RunnableRule<?,?>> list = new ArrayList<>();
 list.add(new AcksTermsSignUpRule());
 list.add(new RunnableRule<String, Double>() {});

您可以直接阅读文档there

Collection>(读作“未知的集合”),即一个 元素类型匹配任何东西的集合

下界通配符将未知类型限制为特定的 类型或该类型的超类型。下界通配符是 使用通配符 ('?') 表示,后跟 super 关键字,后跟其下限:

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-04-25
    • 2021-10-11
    • 1970-01-01
    • 2012-09-13
    • 2015-05-13
    • 1970-01-01
    • 1970-01-01
    • 2011-08-17
    相关资源
    最近更新 更多