0

これは、見たことのある他の 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

この再帰的なジェネリックの使用がコンパイル エラーを引き起こす理由と、チェックされていないキャストの警告をなくすための解決策についての考えは、非常に高く評価されます。

4

3 に答える 3

2

クラスthis内にキーワードを書いています。Entity<X>そう、

this = エンティティ <X>

一方、あなたはではなく を提供Comparatorしました。XEntity<X>

Xオブジェクト内に関連オブジェクトを格納するフィールドを保持し、次のEntity<X>ように記述できます。

結果 = 比較器.比較(これ.getX(),それ);

于 2012-01-31T08:57:27.883 に答える
1

次の2つのクラスを想像してみてください。

class Foo extends Entity<Bar> {}
class Bar extends Entity<Foo> {}

明らかに、比較はX次のインスタンスでのみ呼び出すことはできません。thenのインスタンスで呼び出す場合、FooまたはX = Barその逆の場合。

編集:明確にするために、常に継承型自体をXに置き換えるつもりですが、これは言語やコンパイラによって強制されません。それがあなたの問題の原因です。

于 2012-01-31T08:12:15.447 に答える
0

変!それは完全に幸せです

result = comparator.compare((X)this, that);

では、「これ」が X でない可能性がある状況はありますか? サブクラス化してパラメーターをバインドしないままにしておくという奇妙な順列はありますか? または、バインドされたパラメーターを使用してサブクラスをさらにサブクラス化しますか?

あはは!X が既にバインドされているときにクラスをサブクラス化すると、発生する可能性があります。

…いいえ、そうではありません。認めざるを得ない、私は当惑している。

于 2012-02-03T03:44:10.287 に答える