3

在成功编写了一种方法来完成它应该做的事情之后(下面大大缩短了示例),我想将它重构为不限于返回 a ListofMyEntity而是返回 a List<SomeType extends MyParentEntity>。所以它应该只能接受那些扩展 myMyParentEntity但能够指定另一种类型(List<MyOtherEntity>List<MyAwesomeEntity>)的类型。

缩短示例:

 public static List<MyEntity> getFavList(Context context) {

        String prefKey = buildKey( new MyEntity() );
        List<MyEntity> entityList = new ArrayList<MyEntity>();

        SharedPreferences settings = context.getSharedPreferences(prefKey, 0);

        GSON gson = new GSON();
        MyEntity entity = gson.fromJson(settings.getString(0, null), MyEntity.class);

        entityList.add(entity);

        return entityList;
    }

我搜索了很多,但我没有找到正确的方法来使这项工作没有任何编译器错误。我将不胜感激任何导致解决方案的指针。

4

4 回答 4

2

您将需要传入Class和要传递给的对象buildKey

public static <T extend MyParentEntity> List<T> getFavList(
    Context context, Class<T> clazz, T key
) {

    String prefKey = buildKey(key);
    List<T> entityList = new ArrayList<T>();

    SharedPreferences settings = context.getSharedPreferences(prefKey, 0);

    GSON gson = new GSON();
    MyEntity entity = gson.fromJson(settings.getString(0, null), clazz);

    entityList.add(entity);

    return entityList;
}

(我不知道buildKey应该是什么。)

于 2012-09-18T16:33:36.320 回答
2

必须从方法参数中获取有关具体实现的信息MyParentEntity(不能从返回类型推断 - 废话)。所以你必须修改参数。

我会尝试:

public static <T extends MyParentEntity> List<T> getFavList(Context context, Class<T> clazz) {

        String prefKey = buildKey( clazz.newInstance() );
        List<T> entityList = new ArrayList<T>();

        SharedPreferences settings = context.getSharedPreferences(prefKey, 0);

        GSON gson = new GSON();
        MyEntity entity = gson.fromJson(settings.getString(0, null), clazz);

        entityList.add(entity);

        return entityList;
    }
于 2012-09-18T16:18:02.743 回答
1

由于 Java 具有类型擦除(在此处阅读有关它的内容http://docs.oracle.com/javase/tutorial/java/generics/erasure.html),因此您将无法轻松地获取给定的类型参数List<Something>.

Java中有两个地方可以欺骗类型擦除。一种是通过创建已参数化的事物的子类。Guava 和 Gsons 都使用了这种技巧TypeToken

请参阅下面的示例:

List<MyThing> l = gson.fromJson("[{}, {}]", new TypeToken<List<MyThing>>(){}.getType());

请注意,您在这里创建了一个匿名类,它派生自参数化的 TypeToken - 正如我之前解释的那样,这允许我们在RuntimeList<MyThing>期间保留 Type 。

更多信息可以在 Gson 文档中找到:https ://sites.google.com/site/gson/gson-user-guide 或 StackOverflow,这里:如何使用 GSON 或 Java 中的其他 JSON 库反序列化列表?

PS:我看到你只想返回这个列表中的一个元素(现在?)......?我的回答是实际上从 JSON 中解组这样的元素列表——我猜你接下来会这样做吗?;-) 如果您只想返回“列表中的单个元素”,请使用Collections.singletonList()或 Guava ImmutableList.of(),因为它们是不可变的(一件好事)并且内存占用比“普通列表”低得多。

干杯,康拉德

于 2012-09-18T17:19:08.043 回答
0

正如@keyboardsurfer 已经指出的那样,泛型信息在运行时不可用,因此您还应该向方法提供具体类以便能够实例化它(无论如何您都需要它才能在 中使用它gson.fromJson())。

要做到这一点,只需传递Classof T,这样您就可以参考T.class和制作new T(). 以下问题有更多详细信息:Instantiating a generic class in Java

例如(根据需要添加try/catch子句newInstance()):

public static <T extends MyParentEntity> List<T> getFavList(Context context, Class<T> clazz) {

    String prefKey = buildKey( clazz.newInstance() );
    List<T> entityList = new ArrayList<T>();

    SharedPreferences settings = context.getSharedPreferences(prefKey, 0);

    GSON gson = new GSON();
    T entity = gson.fromJson(settings.getString(0, null), clazz);

    entityList.add(entity);

    return entityList;
}

编译器将接受

List<MyEntity> list = getFavList(ctx, MyEntity.class);
List<MyAwesomeEntity> list = getFavList(ctx, MyAwesomeEntity.class);
于 2012-09-18T16:08:03.543 回答