これは、見たことのある他の 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 Definitionを読む、特にそれが言う部分、
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
この再帰的なジェネリックの使用がコンパイル エラーを引き起こす理由と、チェックされていないキャストの警告をなくすための解決策についての考えは、非常に高く評価されます。