1

このメモリクラスを作成しました:

public class Memory {
    private final Hashtable<String, String> data;
    private final Gson gson;

    public Memory() {
        this.data = new Hashtable<String, String>();
        this.gson = new Gson();
    }

    public <T> void set(String key, List<T> value) {
        this.data.put(key, this.gson.toJson(value));
    }

    public <T> List<T> get(String key, Class<T> cls) {
        Type type = new TypeToken<List<T>>() {}.getType();
        return this.gson.fromJson(this.data.get(key), type);
    }
}


ジェネリック型のリストを json に格納してから、それらを逆シリアル化できます。
しかし、たとえば次のように使用しようとすると:

public class User {
    private int id;
    private String username;

    public User() { }

    public User(int id, String username) {
        this.id = id;
        this.username = username;
    }
}

Memory memory = new Memory();
List<User> users = new ArrayList<User>();
// add users
memory.set("users", users);

// now get the users back
List<User> copy = memory.get("users", User.class);

Gson は、Users ではなく StringMap の ArrayList を返します。
これは明らかに私が使用しているジェネリックと関係がありますが、それを回避する方法はありますか?

ありがとう。

4

1 に答える 1

2

ここでの実際の失敗は、Java Generics が許容する明白な矛盾によって強調されList<User>ますcom.google.gson.internal.StringMap。しかし、それはまったく別のトピックです。

当面の問題は、タイプ トークン クラスを適切に使用していないことです。トークンの要点は、具象型でクラスを拡張する必要があるということですが、コンパイル時に検証されてから消去されるメソッドレベルのジェネリックパラメーターを使用してクラスをインスタンス化しています(その後、実行時に使用できなくなります)。しかし、型トークンの要点は一般的な情報を保持することなので、モデルは吹き飛ばされます。

正直なところ、これはトークンの実装の失敗です。たとえば、コンストラクター コードをTypeReferenceJackson の実装と比較すると、 Jackson が具体的なパラメーターが使用可能であることを実際に検証していることがわかります。

31    protected TypeReference()
32    {
33        Type superClass = getClass().getGenericSuperclass();
34        if (superClass instanceof Class<?>) { // sanity check, should never happen
35            throw new IllegalArgumentException("Internal error: TypeReference constructed without actual type information");
36        }
45    }

最も簡単な解決策は、単純に型 (トークン) の作成を呼び出し元の責任にし、格納および/または取得するデータと共に渡すことです。

public <T> List<T> get(String key, Type type) {
    return this.gson.fromJson(this.data.get(key), type);
}

public <T> void set(String key, List<T> value, Type type) {
    this.data.put(key, this.gson.toJson(value, type));
}
于 2013-04-07T17:48:16.370 に答える