2

タイプとは、次のことを可能にするものです。

public class AnyObject{

    List<this.type> list;   

}

私は次のことがうまくいかないことを知っています。

public class AnyObject{

    List<this.getClass()> list;   

}

では、たとえば酒など、これが何であれ、タイプのリストを作成するにはどうすればよいでしょうか。

- - - - - - - - アップデート - - - - - - - -

申し訳ありませんが、私は明確ではなかったと思います。タイプの消去を回避する方法はないようですが、私の問題を解決する方法がまだある場合は、もっと詳しく説明します。開示、これはObjectifyの質問です。すみません、今見に来ました。

ほら、できる限り明確に...

Objectiy を使用して GAE データストアに保持する予定のすべてのエンティティについてKey<?>、id フィールドと親フィールドを使用して Objectify を生成するメソッドが必要です。このメソッドを呼び出しましょうgenerateKey()。これがどのように見えるかです。

public Key<MyEntity> generateKey() {      
    Key<MyEntity> key = Key.create(this.parent, MyEntity.class, this.id);
    return key;
}

問題は、作成するすべてのエンティティに対して、多かれ少なかれ、この正確なコードを書かなければならないことです。実は他にも繰り返しコードはありますが、私の言いたいことは、この繰り返しコードだけで成り立ちます。

だから私はこれを試しました。MyProjectEntity というクラスを作成し、すべてのエンティティにそれを拡張させました。generateKey()次に、ジェネリックを使用してメソッドを実装しました。

public abstract class MyProjectEntity<T, Y> {

    @Id     Long id;
    @Parent Key<T> parentKey;

    public Key<Y> generateKey() {
        Key<Y> key = Key.create(this.parentKey, this.getClass(), this.id);
        return key;
    }          

}

次に、作成した MyProjectEntity という新しいクラスを使用して、すべてのエンティティ クラスを拡張しました。そんな...

@Entity
public class MyEntity extends MyProjectEntity<MyEntityParent> {...}

これで、すべてのエンティティにgenerateKey()メソッドが追加されましたが、うまくいきませんでした。Objectify は私に怒鳴り、IllegalArgumentException と言いました。T 型の Key を宣言できません。

それから試してみKey<Object>ましたが、Objectify はまだ満足していませんでした。Objectify は、Object は登録されたエンティティではないと言いました。オブジェクトを登録する必要があります!?!? そして、それは、Objectify が提供する型付きキーの要点をすべて失ってしまいます。

良い解決策はありますか。ありがとう!

-- 更新 2 --

誰かが Key.create(myEntity) を指摘したので、私は私の完全な使用を指摘する必要があります...

/**********************************************************************************************************************
 * Constructors END & Identification and Relationship Methods BEGIN
 **********************************************************************************************************************/

    @ApiSerializationProperty(name = "id")
    public String getWebSafeKey() {

        String webSafeKey = getKey().getString();

        return webSafeKey;

    }

    public void setWebSafeKey(String webSafeKey) throws BadRequestException {

        try {
            Key<MyEntity> key = Key.create(webSafeKey);
            setKey(key);

        } catch (IllegalArgumentException illegalArgumentException) {
            throw new BadRequestException(ErrorMessage.INVALID_ID);
        }

    }

    @ApiSerializationProperty(name = "parentId")
    public String getParentWebSafeKey() {
        String webSafeKey = parent.getString();
        return webSafeKey;
    }

    public void setParentWebSafeKey(String parentWebSafeKey) throws BadRequestException {

        if (id == null) {
            try {
                parent = Key.create(parentWebSafeKey);
            } catch (IllegalArgumentException illegalArgumentException) {
                throw new BadRequestException(ErrorMessage.invalidParentId("Property"));
            }

        } else {
            /* Do nothing. Only set parent here if setWebSafeKey is never called, such as during a create. */
        }

    }

    @ApiSerializationProperty(ignored = AnnotationBoolean.TRUE)
    public Key<MyEntity> getParentKey() {
        return parent;
    }

    public void setParentKey(Key<MyEntity> parentKey) {
        this.parent = parentKey;
    }

    @ApiSerializationProperty(ignored = AnnotationBoolean.TRUE)
    public Key<MyEntity> getKey() {

        Key<MyEntity> key = Key.create(parent, MyEntity.class, id);

        return key;

    }

    public void setKey(Key<MyEntity> key) {
        id = key.getId();
        parent = key.getParent();
    }

    public boolean webSafeKeyEquals(String webSafeKey) {

        boolean equals;

        if (id !=null & parent !=null) {
            equals = getWebSafeKey().equals(webSafeKey);
        } else {
            equals = false;
        }

        return equals;

    }

/**********************************************************************************************************************
 * Identification Methods END & Other Getters and Setters BEGIN
 **********************************************************************************************************************/

MyEntity を実際のエンティティ名に置き換えて、作成するすべてのエンティティにこれをすべて挿入する必要があります。タイピングだけではありません。このコードはエンティティ クラスに属していませんが、抽象的な親に属しています。クラス内の特定のエンティティに固有のコードのみを使用できれば、モデルはよりクリーンになり、拡張が容易になります。再度、感謝します。

4

5 に答える 5

3

List<this.getClass()> list;型パラメーターは Java のコンパイル時のものであるため、これは意味がありません。この情報は実行時に消去されます。

于 2013-10-28T23:24:39.370 に答える
3

これでは意味がありません。考慮してください: の型が何であるかは決してわかりませんlistlistが何らかのクラスの何らかのメソッドで使用されていると仮定すると、それは常にthisサブクラスのインスタンスである可能性があります。Listしたがって、の型ののパラメータはlist、どのコードでも想定できません。それが決して知ることができないなら、それのポイントは何ですか?を使用するだけList<?>です。

ジェネリックは純粋にコンパイル時のものです。したがって、何かのランタイム クラスに依存しても意味がありません。

私はあなたが持っていることをお勧めします

public class AnyObject<T> {
    List<T> list;
}

たとえば、 になりFooたいクラスは、 を実装または継承する必要があります。listList<Foo>AnyObject<Foo>

于 2013-10-28T23:06:42.980 に答える
1

Objectify に精通していなくても、ジェネリックだけですが、Key.create<T>自体が、返されたキーの型のジェネリック引数を取ることになっていることがわかります。したがって、スーパークラスでメソッドを呼び出すときは、次のことを行う必要があります。

Key<Y> key = Key.<Y>create(this.parentKey, this.getClass(), this.id);

エラーを修正するには、単にそれを行う必要があるだけかもしれません (とにかくそれを行う必要があります)。それ以外の場合、Key.create は new をインスタンス化しようとします。Key<Y>メソッドが型引数を要求するときに型引数を宣言しないことは多かれ少なかれ有効ですが、明らかに Key.create はそれを好まない可能性があります。

Ts と Ys も混同しているように見えるので、もう一度確認する必要があると思います。現在、 Key.create aKey<T>をパラメーターとして処理していますが、 a を返したいと考えていますKey<Y>。また、クラスを宣言すると、<T, Y>それを拡張するのは違法になるはず<MyEntityParent>です。

あなたのコードを見ると、あなたがしようとしているのは、呼び出し元のメソッドと同じクラスの Key を作成することだと思います。MyEntity の IE クラス generateKey は を返す必要がありKey<MyEntity>ます。これを行う適切な方法は次のようになると思います(これは有効です):

public abstract class MyProjectEntity<T, K> {
    Long id;
    Key<K> parentKey;

    public Key<K> generateKey() {
        return Key.<K>create(parentKey, this.getClass(), id);
    }
}

public class MyEntity extends MyEntityParent<MyEntityParent, MyEntity> {
    /*
     * K is now MyEntity and parentKey is a Key<MyEntity>
     * generateKey now does the following:
     *
     * public Key<MyEntity> generateKey() {
     *     return Key.<MyEntity>create(parentKey, MyEntity.class, id);
     * }
     *
     */
}

タイプを適切に宣言していないため、機能しない例でエラーが発生しているようです。しかし、あなたの T と Y がどうあるべきかがはっきりしないので、わかりにくいです。宣言されている型の 1 つだけを表示し、少なくとも generateKey メソッドで Key.create を処理してKey<T>いますが、 を返したいと考えていKey<Y>ます。

または、Objectify API でのエンティティの登録をご覧になることをお勧めします。IE の場合、次のようなことを行う必要があるようです。これが、エラーが発生する理由として考えられます。

static {
    ObjectifyService.register(MyEntityParent.class);
}

とにかく、Java ジェネリックの世界では、他に何かが起こっていない限り、体操をしなくてもこのようなことができるはずです。消去の性質は、実行時に型を見つけることができないということですが、T のすべてのインスタンスが引数の型に置き換えられるため、型は本質的に「既知」です。

public abstract class MyProjectEntity<T> {
    Key<T> parentKey;
}

になる

public class MyEntity extends MyProjectEntity<MyEntityParent> {
    Key<MyEntityParent> parentKey;
}

parentKey が Type かどうかはわかりません<MyEntityParent>その型です。java.util.List のようなものでこれを明らかに確認できます。ここで、次のようにします。

List<Double> doubleList = new ArrayList<Double>(0);
doubleList.add("a string");

コンパイラ エラーを無視してプログラムを実行しようとすると、次のようになります。

Uncompilable source code - Erroneous sym type: java.util.ArrayList.add
java.lang.RuntimeException: Uncompilable source code - Erroneous sym type: java.util.ArrayList.add

リストDouble のインスタンスのみを保持するためです。この状況は、ArrayList の add メソッドのインスタンスが Double を引数として正式に受け取る匿名クラスと比較できます。これをやろうとしただけなので、コンパイルできません:

public void add(Double element) {
    // add the element to the array
}

list.add("a string");

これは明らかに違法です。この ArrayList の基になる配列は引き続き Object[] ですが、メソッドは型を反映するように変更され、実行時に配列が Double 要素のみを安全に保持するようになります。

したがって、関連するコードを省略しない限り、複数の問題があるように見えるため、私が言及したことを確認することをお勧めします。

于 2013-11-05T17:17:05.000 に答える
0

私はあなたの問題を理解していると思います。これがあなたがそれを行う方法です。秘訣は、サブクラスを親クラスのジェネリック パラメータとして渡すことです。

class Parent<T> {
    T doStuff() {
        T res = null;
        // res = ..... this.getClass() is ok...
        return res;
    }
}

public class SelfGerenic extends Parent<SelfGerenic> {
}

public class OtherSubClass extends Parent<OtherSubClass> {
}
于 2013-11-04T14:26:02.350 に答える