Предположим, что требование должно быть однородным - violations
должно иметь тип Set<ConstraintViolation<X>>
для некоторых X
.
Самый естественный способ сделать это - сделать ValidationException
универсальным:
public class ValidationException<T> extends Exception
Set<ConstraintViolation<T>> violations;
public ValidationException(String msg, Set<ConstraintViolation<T>> violations)
Конечно, Java не допускает этого для подтипов Throwable по причинам, выходящим за рамки системы типов. Это не наша вина, поэтому мы не виноваты в том, что изобрели какой-то обходной путь:
public class ValidationException extends Exception
{
static class SetConstraintViolation<T> extends HashSet<ConstraintViolation<T>>
{
SetConstraintViolation(Set<ConstraintViolation<T>> violations)
{
super(violations);
}
}
// this is homogeneous, though X is unknown
private SetConstraintViolation<?> violations;
public <T> ValidationException(String msg, Set<ConstraintViolation<T>> violations)
{
super(msg);
this.violations = new SetConstraintViolation<T>(violations);
}
public <T> Set<ConstraintViolation<T>> getViolations()
{
return (Set<ConstraintViolation<T>>)violations;
}
}
void test()
{
Set<ConstraintViolation<User>> v = ...;
ValidationException e = new <User>ValidationException("", v);
Set<ConstraintViolation<User>> v2 = e.getViolations();
Set<ConstraintViolation<Pswd>> v3 = e.getViolations();
Set<? extends ConstraintViolation<?>> v4 = e.getViolations();
}
Примечание: приведение в getViolations()
безопасно только в том случае, если сайт вызова указан правильно T
, как в случае v2
. В случае v3 приведение неверно - компилятор не напрасно предупредил нас.
Сайт вызова, вероятно, не знает и не заботится о точном T
, как в случае с v4. Сайт вызова может преобразовать нарушения, однородную коллекцию определенного неизвестного типа, в более общий тип только для чтения с использованием групповых символов. Это довольно неловко. Если case v4
является наиболее частым случаем использования, мы должны предоставить метод, который просто возвращает Set<ConstraintViolation<?>>
. Мы не можем напрямую вернуть violations
, это небезопасно. Требуется копия. Если v4
является единственным вариантом использования, то это решение действительно становится тем же решением, которое предлагали предыдущие респонденты.