使用带有嵌套“?”的 Set 调用 java 方法泛型

Calling java method with Set with nested "?" generic type

我在可重复使用的 class:

中有这样的方法
public String buildMessageForViolation(ConstraintViolation<?> constraintViolation) {
    return constraintViolation.getPropertyPath().toString().replace(".<collection element>", "") + ": " + constraintViolation.getMessage();
}

它是从另一个 class 调用的,像这样:

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

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

所以,然后我将其添加到可重复使用的 class:

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>>)

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

有什么简单的方法可以解决这个问题吗?

更新:

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

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

客户端代码可以改为这样做:

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

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

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

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

我会把方法写成:

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);