验证方法(捕获#2-of?extends Object)类型Validator <capture#2-of?=“”extends =“”object =“”>不适用于参数(String)</capture#2 -of>

时间:2013-09-17 05:55:58

标签: java generics

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

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

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类的任何内容,对吗?

有人能指出我做错了什么或者指出了我正确的方向吗? 感谢。

2 个答案:

答案 0 :(得分:5)

另外,? extends Object?没有什么不同。但是,这不是问题的根源。

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

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

答案 1 :(得分: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());

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