Этот дизайн похож на другие шаблоны JPA BaseEntity, которые вы, возможно, видели:
@MappedSuperclass()
public abstract class Entity<X extends Entity<X>>
implements
Comparable<X>,
Serializable
{
private static final long serialVersionUID = 1L;
private Long id;
private Date timeStamp;
...
// Simply compare fields in subclass until difference is discovered
private int compareSubclassFields(X that)
{
int result = 0;
for(Comparator<X> comparator : getComparators())
{
result = comparator.compare(this,that); <<=== compilation error
if(result != 0) { break; }
}
return result;
}
/**
* Entity subclasses provide a list of their own special
* comparators that can contribute to the comparison.
*/
protected abstract List<Comparator<X>> getComparators();
}
Вот пример класса, расширяющего Entity:
public class User extends Entity<User>
{
private static final long serialVersionUID = 1L;
private String firstName;
private String lastName;
private String email;
...
@Override
public List<Comparator<User>> getComparators()
{
List<Comparator<User>> result =
new ArrayList<Comparator<User>>();
result.add(getLastNameComparator()); // Sort first on last name
result.add(getFirstNameComparator());// Next, by first name
result.add(getEmailComparator()); // Finally, by email (unique)
return result;
}
}
Когда я компилируюЯ получаю следующую ошибку:
error: method compare in interface Comparator<T> cannot be
applied to given types;
result = comparator.compare(this,that);
^
required: X,X
found: Entity<X>,X
reason: actual argument Entity<X> cannot be converted to
X by method invocation conversion
where X,T are type-variables:
X extends Entity<X> declared in class Entity
T extends Object declared in interface Comparator
Чтение Определение Java Enum , в частности, часть, в которой написано:
public class StatusCode extends Enum<StatusCode>
Теперь, если выпроверьте ограничения, у нас есть Enum - так что E = StatusCode.Давайте проверим: расширяет ли E Enum?Да!Мы в порядке.
Я предполагаю, что в моем примере, где X extends Entity<X>
, 'this' будет экземпляром User
, а не Entity<User>
.Более того, поскольку Entity является абстрактным классом, он должен быть расширен и, следовательно, compareNonIdFields
может быть вызван только экземпляром X - на самом себе.Конечно, когда я произношу, я получаю неконтролируемое предупреждение:
warning: [unchecked] unchecked cast
result = comparator.compare(((X)this),that);
^
required: X
found: Entity<X>
where X is a type-variable:
X extends Entity<X> declared in class Entity
1 warning
Мысли о том, почему это рекурсивное универсальное использование вызывает ошибку компиляции, и решения, позволяющие убрать предупреждение о неконтролируемом приведении, будут с благодарностью.