如何将方法重构为只接受类型子集的泛型方法?

时间:2012-09-18 16:00:31

标签: java generics refactoring

在成功编写了一个完成它应该做的事情的方法之后(下面简要缩短了示例)我想重构它不仅限于返回List MyEntity而是List<SomeType extends MyParentEntity> 。因此,它应该只能接受扩展我的MyParentEntity但能够指定其他类型(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;
    }

我google了很多,但我没有找到正确的方法来使这项工作没有任何编译器错误。我很感激能够找到解决方案的任何指示。

4 个答案:

答案 0 :(得分: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;
    }

答案 1 :(得分: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应该是什么。)

答案 2 :(得分: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 - 正如我之前解释的那样,这允许我们在运行时期间保持List<MyThing>类型。

可在此处的Gson文档中找到更多内容:https://sites.google.com/site/gson/gson-user-guide 或者在StackOverflow上,这里:How to deserialize a list using GSON or another JSON library in Java?

PS:我看到你只想在这个列表中返回一个元素(现在?)......?我的答案是关于从JSON实际解组这些元素列表 - 我猜你接下来会做什么? ;-)如果您只想返回“列表中的单个元素”,请使用Collections.singletonList()或Guava的ImmutableList.of(),因为它们是不可变的(一件好事)并且具有比“正常名单“。

干杯, 康拉德

答案 3 :(得分:0)

正如@keyboardsurfer已经指出的那样,泛型信息在运行时是不可用的,所以你也应该为方法提供具体的类来实例化它(无论如何你需要它在{{1中使用它) }})。

为此,只需传递gson.fromJson()的{​​{1}},即可引用Class并制作T。以下问题有更多详细信息:Instantiating a generic class in Java

例如(根据需要为T.class添加new T()子句):

try/catch

编译器将接受

newInstance()