1

很抱歉将错误直接作为标题,但我找不到更好的标题。

我有一个定义如下的接口,用作我所有验证器类的蓝图:

public interface Validator<T> {
    public boolean validate(T item);
}

然后我有一些可以实现它的类,假设其中之一是这样的:

public class EmptyStringValidator implements Validator<String> {
    private final String _errorMessage;

    public EmptyStringValidator() {
            this("String cannot be empty.");
    }

    public EmptyStringValidator(String message) {
            this._errorMessage = message;
    }

    @Override
    public String getMessage() {
            return this._errorMessage;
    }

    @Override
    public boolean validate(String item) {
            return gsi.application.core.Validation.isEmptyString(item);
    }

}

我想把它全部放在一个数组中,然后在一个循环中调用它。所以这是我正在使用的代码:

public List<Validator<? extends Object>> validators;

public FormItem<T> addValidator(Validator<? extends Object> validator) {
    this.validators.add(validator);
    return this;
}

public boolean validate() {
    for (Validator<? extends Object> validator : this.validators)
        if (!validator.validate(this.getInputValue())) {
            this._errorMessage = validator.getMessage();
            return false;
        }
    return true;
}

但是,该代码在函数中给出了错误validate(),特别是在这部分:

validator.validate(this.getInputValue())

它给了我我提到的错误

The method validate(capture#2-of ? extends Object) in the type Validator<capture#2-of ? extends Object> is not applicable for the arguments (String)

我的理解是没有意义的。据我了解<? extends Object>,应该接受从 Object 类派生的任何东西,对吗?

谁能指出我做错了什么或指出我正确的方向?谢谢。

4

2 回答 2

5

顺便说一句,? extends Object和说没有什么不同?。然而,这不是你问题的根源。

问题是这validators是一个List<Validator<? extends Object>>. 换句话说,每个元素都可以是任何类型的Validator<T>,不一定是Validator<String>。所以你可以把aValidator<String>放进去,但是当你拉出一个元素时你不知道Validator它是什么类型,所以你不知道它是否与返回的类型兼容this.getInputValue()

最简单的解决方法是为类型参数指定一个具体类型(例如String:)。更复杂的解决方法是使用类型变量代替? extends Object,并让getInputValue()的类型签名使用相同的类型变量。您需要限制类型,使getInputValue()的返回类型可分配给 的参数validate()

于 2013-09-17T06:03:15.507 回答
0

对于收集的验证器,一个更好的类型通常是Validator<? super T>,输入类型在哪里T,在这种情况下是String

这种方式addValidator(Validator<? super String> validator)接受Validator<String>但也Validator<CharSequence>Validator<Object>

例如:

class LongerThan10 implements Validator<CharSequence> {
    @Override
    public boolean validate(CharSequence item) {
        return item.length() > 10;
    }
}

formItem.addValidator(str -> !str.isBlank())
formItem.addValidator(new LongerThan10());

在这种特定情况下,它没有多大意义,但接受通常使用超类型的验证器是一个好主意。

于 2020-08-07T12:45:28.017 回答