用嵌套“?”调用带有Set的java方法通用类型

时间:2017-06-22 19:17:59

标签: java generics collections generic-collections

我在可重用的类中有这样的方法:

public String buildMessageForViolation(ConstraintViolation<?> constraintViolation) {
    return constraintViolation.getPropertyPath().toString().replace(".<collection element>", "") + ": " + constraintViolation.getMessage();
}

从另一个类中调用它:

 fieldValidator.appendErrorMessage(getUslValidator().buildMessageWithProperty(constraintViolations.iterator().next()) +
                (constraintViolations.size() > 1 ? ", and other errors" : ""));

所以,因为我希望在许多类中重复这个块,所以我想重构它,因此复杂性在可重用的类中,而不是在客户端代码中。

因此,我将此添加到可重用的类中:

public String buildMessageForViolations(Set<ConstraintViolation<?>> constraintViolations) {
    return buildMessageForViolation(constraintViolations.iterator().next()) +
            (constraintViolations.size() > 1 ? ", and other errors" : "");
}

然后将客户端代码更改为:

fieldValidator.appendErrorMessage(getUslValidator().buildMessageForViolations(constraintViolations));

这不编译,说:

The method buildMessageForViolations(Set<ConstraintViolation<?>>) in the type USLValidator is not applicable for the arguments (Set<ConstraintViolation<ClientSpecificClassName>>)

显然,这与我指定“?”的事实有关。对于嵌套类型参数。从我的观点来看,这是合适的,因为可重用的类不关心ConstraintViolation的类型参数。

我能解决这个问题吗?

更新

我正在阅读发布到此的答案以及随后对答案的编辑,但之后由于某种原因将其删除(猜测响应者放弃了尝试使其正确)。

虽然答案仍然存在,但它至少帮助我找到了一个合理的解决方法。

客户端代码可以改为:

fieldValidator.appendErrorMessage(getUslValidator().buildMessageForViolations(new HashSet<ConstraintViolation<?>>(constraintViolations)));

这至少比原版好一点,尽管还有一些人们必须记住的样板。

2 个答案:

答案 0 :(得分:0)

嵌套通配符可能会导致一些意外的不兼容性。试试这个:

public String buildMessageForViolations(Set<? extends ConstraintViolation<?>> constraintViolations) {

答案 1 :(得分:0)

我会把方法写成:

public String buildMessageForViolations(Set<ConstraintViolation> constraintViolations) {..}

这告诉编译器它需要一组任何类型的ConstraintViolation。我认为在这种情况下,这就是你要告诉编译器的内容。

使用客户端代码:

ConstraintViolation cv = new StringConstraintViolation();
USLValidator uslValidator = new USLValidator();

Set<ConstraintViolation> constraintViolationSet = new HashSet<>();
constraintViolationSet.add(cv);
uslValidator.buildMessageForViolations(constraintViolationSet);