【问题标题】:Java Generics: function parameter for a set of generic typed objectsJava 泛型:一组泛型类型对象的函数参数
【发布时间】:2014-03-24 08:42:36
【问题描述】:

我正在使用 javax.validation / Hibernate 验证。 为了验证带注释的(例如属性上的@NotNull)bean,hibernate 验证器与 javax.validation 接口一起使用:

Validator validator = Validation.buildDefaultValidatorFactory().getValidator();

public interface Validator {
    <T> Set<ConstraintViolation<T>> validate(T object, Class<?>... groups);
}

public interface ConstraintViolation<T> {
    String getMessage();
    Path getPropertyPath(); 
    T getRootBean();
}

目标是编写一个方法,它接受不同类型的集合,例如:

Set<ConstraintViolation<TaskList>> violationsTaskList = validator.validate(taskList);
Set<ConstraintViolation<TaskItem>> violationsTaskItem = validator.validate(taskItem);

public void consumeViolations(Set<ConstraintViolation<?> violations) {
    // Do something meaningful...
    violations.getMessage();
}

使用通配符 ?最好认为我到现在为止都想出了,但编译器拒绝了它并显示以下消息:

consumeViolations(....<?>) cannot be applied to consumeViolations(....<TaskList>)

我不想为每个类型 T 编写此方法只是为了调用 getMessage() 并将其传递给下一个方法。

这样的方法可以写吗?我只想访问 ConstraintViolation 接口的方法,这些方法不依赖于类型 T,如 String getMessage()。

【问题讨论】:

    标签: java generics hibernate-validator


    【解决方案1】:

    我认为你需要的是

    public void consumeViolations(Set<? extends ConstraintViolation<?>> violations) {}
    

    或喜欢

    public <T, V extends ConstraintViolation<T>> void consumeViolations(Set<V> violations) {}
    

    取决于您需要对方法内的 Set 执行什么操作。

    这只是泛型的常规行为,通常不是协变的。你可能知道a List&lt;Dog&gt; is not a List&lt;Animal&gt;,同样的事情也适用于这里。

    【讨论】:

    • 公共 API 的签名不应依赖于您在方法中执行的操作
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-10-06
    • 2012-01-16
    • 1970-01-01
    • 1970-01-01
    • 2016-09-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多