4

如何在 Java 中正确执行以下操作?我想要一个可以创建对象列表的通用例程。在这个例程中,我希望这些对象的类的构造函数支持特定的参数。

澄清一下:我希望这个例程List<T>从 JSON 字符串创建一个。这是更大的反序列化代码的一部分。如果我能以某种方式指定每个支持T的实现一个构造函数,该构造函数创建T给定的 a JSONObject,那么我可以编写如下例程:

interface CreatableFromJSONObject<T> {
    T(JSONObject object);     // Complains about missing return type.
} 

static <T> List<T extends CreatableFromJSONObject> jsonArrayToList(JSONArray array) {
    List<T> result = new ArrayList<T>();
    for (int i = 0; i < array.length; ++i) {
         JSONObject jsonObject = array.getJSONObject(i);
         result.add(T(jsonObject));    // If T has one constructor with 1 one argument JSONObject
    }
    return result;
}

然后用一个实现这个接口的示例类

class SomeClass implements CreatableFromJSONObject {
    SomeClass(JSONObject object) throws JSONException {
        // implementation here
    }
}

我可以使用所需的方法:

List<SomeClass> list = jsonArrayToList<SomeClass>(someJSONArray);

现在,在 StackOverflow 上对此有相当多的点击,所以我了解到我上面概述的内容是不可能的,因为 Java不支持在接口中指定特定的构造函数,也不支持静态方法(这将是一个替代路线同一件事,但由于同样的原因不可能)。

那么,实现这一目标的最佳方法是什么?

我目前的最佳尝试如下:

public static <T> List<T> jsonArrayToList(final JSONArray jsonArray, Constructor<T> fromJSONObjectConstructor) {
    List<T> result = new ArrayList<T>();
    try {
        for (int i = 0; i < jsonArray.length(); i++) {
            result.add(fromJSONObjectConstructor.newInstance(jsonArray.getJSONObject(i)));
        }
    } catch (InvocationTargetException e) {
        throw new RuntimeException(e);
    } catch (InstantiationException e) {
        throw new RuntimeException(e);
    } catch (IllegalAccessException e) {
        throw new RuntimeException(e);
    } catch (JSONException e) {
        throw new RuntimeException(e);
    }
    return result;
}

然后添加到此方法应支持的每个类:

public class SomeClass {
    public static final Constructor<SomeClass> jsonObjectConstructor;
    static {
        try {
            jsonObjectConstructor = CafellowEntity.class.getConstructor(JSONObject.class);
        } catch (NoSuchMethodException e) {
            throw new RuntimeException(e);
        }
    }

    SomeClass(JSONObject object) throws JSONException {
        // Implementation here
    }
}

我用作

List<SomeClass> list = jsonArrayToList(myJSONArray, SomeClass.jsonObjectConstructor);

这是我能想到的最漂亮的解决方案,除了根本不使用通用实现之外,只需将(在这种情况下)实际上正在执行工作的几行代码放在我需要它们用于特定的地方班级。

有什么建议么?与替代解决方案相比,此解决方案的性能如何?通过不支持它就像这样 Java 可能告诉我我不应该想要这样做,但这并不能阻止我想知道它。

4

2 回答 2

4

除非您正在进行某种不寻常的反序列化,否则这种设计过于复杂且容易出错。Android 捆绑了一个出色的 JSON 解析器,它已经可以做到这一点,而且做得很好。您当前为其定义自定义构造函数的每种类型都可以使用一行代码进行反序列化:

final CustomObj obj = new Gson().fromJson(jsonObj.toString(), CustomObj.class);

将其合并到您现有的方法中,您最终会得到:

public static <T> List<T> jsonArrayToList(final JSONArray jsonArray,
        Class<T> clazz) {
    if (jsonArray == null || clazz == null)
        return null;

    final Gson gson = new Gson();
    List<T> result = new ArrayList<T>(jsonArray.length());
    for (int i = 0; i < jsonArray.length(); i++) {
        try {
            result.add(gson.fromJson(jsonArray.getJSONObject(i).toString(),
                    clazz));
        } catch (final JSONException je) {
            je.printStackTrace();
            return null;
        }
    }

    return result;
}
于 2013-02-25T22:28:51.390 回答
0

您可以通过省略构造函数实例并改用 clazz 实例来简化您的解决方案。所以签名jsonArrayToList()将是:

public static <T> List<T> jsonArrayToList(final JSONArray jsonArray, Class<T> clazz); 

然后调用构造函数clazz.newInstance();

如果您事先知道类的类型,这将起作用。

于 2013-02-25T22:28:19.943 回答