如何在Java中正确执行以下操作?我想有一个可以创建对象列表的通用例程。在这个例程中,我希望这些对象的类的构造函数支持一个特定的参数。
澄清:我希望此例程从JSON字符串创建List<T>
。这是更大的反序列化代码的一部分。如果我能以某种方式指定每个受支持的T
实现一个构造函数,在T
给出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);
我可以使用所需的方法:
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;
}
现在,在StackOverflow上有相当多的点击,所以我已经了解到我上面概述的内容是不可能的,因为Java does not support specifying a particular constructor in an interface和not for static methods(这将是另一种途径同样的事情并不可能出于同样的原因)。
那么,实现这一目标的最佳途径是什么?
我目前的最佳尝试如下:
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);
我用作
{{1}}
除了完全没有使用通用实现之外,这是我能想到的最漂亮的解决方案,只需将(在这种情况下)几行代码放在我需要它们的任何地方的实际工作中对于特定的课程。
有什么建议吗?这与替代解决方案的性能如何?通过不支持它就像这样Java可能告诉我我不应该这样做,但这并不妨碍我对此感到疑惑。
答案 0 :(得分: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;
}
答案 1 :(得分:0)
您可以通过省略构造函数实例并使用clazz实例来简化解决方案。所以jsonArrayToList()
的签名是:
public static <T> List<T> jsonArrayToList(final JSONArray jsonArray, Class<T> clazz);
然后按clazz.newInstance();
如果您事先知道班级的类型,这将有效。