Java 将泛型类型与构造函数上的规范一起使用

Java 将泛型类型与构造函数上的规范一起使用,java,android,interface,Java,Android,Interface,如何在Java中正确执行以下操作?我想有一个通用的例程,可以创建一个对象列表。在这个例程中,我希望这些对象类的构造函数支持一个特定的参数 澄清一下:我希望这个例程从JSON字符串创建一个列表。这是更大的反序列化代码的一部分。如果我可以指定每个支持的T实现一个构造函数,在给定JSONObject的情况下创建T,那么我可以编写如下例程: interface CreatableFromJSONObject<T> { T(JSONObject object); // Comp

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

澄清一下:我希望这个例程从JSON字符串创建一个
列表。这是更大的反序列化代码的一部分。如果我可以指定每个支持的
T
实现一个构造函数,在给定
JSONObject
的情况下创建
T
,那么我可以编写如下例程:

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;
}
我可以使用所需的方法:

List<SomeClass> list = jsonArrayToList<SomeClass>(someJSONArray);
List List=jsonArrayToList(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;
}
publicstaticlist-jsonArrayToList(最终的JSONArray-JSONArray,来自jsonobjectconstructor的构造函数){
列表结果=新建ArrayList();
试一试{
for(int i=0;i
然后添加到此方法应支持的每个类:

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
    }
}
公共类SomeClass{
公共静态最终构造函数JSONObject构造函数;
静止的{
试一试{
jsonObjectConstructor=cafellowenty.class.getConstructor(JSONObject.class);
}捕获(无此方法例外){
抛出新的运行时异常(e);
}
}
SomeClass(JSONObject对象)抛出JSONException{
//在这里实现
}
}
我用它作为

List<SomeClass> list = jsonArrayToList(myJSONArray, SomeClass.jsonObjectConstructor);
List List=jsonArrayToList(myJSONArray,SomeClass.jsonObjectConstructor);
这是我能想到的最漂亮的解决方案,除了完全不使用泛型实现之外,只需将(在本例中)实际在例程中执行工作的几行代码放在特定类需要它们的任何地方


有什么建议吗?与其他解决方案相比,该解决方案的性能如何?不支持它,就像Java告诉我不应该这样做一样,但这并不能阻止我对它产生疑问。

您可以通过省略构造函数实例而使用clazz实例来简化您的解决方案。因此,
jsonArrayToList()
的签名应该是:

public static <T> List<T> jsonArrayToList(final JSONArray jsonArray, Class<T> clazz); 
publicstaticlist-jsonArrayToList(最终的JSONArray-JSONArray,类clazz);
然后通过
clazz.newInstance()调用构造函数


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

除非您进行某种不寻常的反序列化,否则此设计过于复杂且容易出错。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;
}
公共静态列表jsonArrayToList(最终JSONArray JSONArray,
课程名称(clazz){
if(jsonArray==null | | clazz==null)
返回null;
最终Gson Gson=新Gson();
列表结果=新的ArrayList(jsonArray.length());
for(int i=0;i
您真正想要完成的是什么?您正在传递的这些类型中进行自定义反序列化吗?是的,这是进行JSON反序列化的代码的一部分。在特定类的构造函数中,我阅读了
JSONObject
,并使用其内容设置了新实例的字段。这在我使用的许多类中都很常见,我希望使用这种通用方法来反序列化JSON数组。它基本上为您完成了所有的序列化/反序列化。这当然清理了丑陋的构造函数引用,但我似乎无法将我的
JSONObject
作为参数传递给
newInstance
。那么,我应该把特定于类的反序列化代码放在哪里呢?@MartijndeMilliano Jiri在答案中遗漏了一些东西。首先需要调用
constructor=clazz.getConstructor(JSONObject.class),然后可以使用
构造函数.newInstance(对象)
@SimonAndréForsberg感谢您的澄清!我接受这个答案,因为它更接近这个问题,它使用Android内置的JSON序列化/反序列化;对于一个新的项目,我肯定会调查Jackson和Gson。@MartijndeMilliano Jiris的答案主要基于您问题中的代码,没有使用Android中内置的JSON序列化。感知的答案确实如此。我强烈推荐这个答案。@MartijndeMilliano它也是直接在类上定义的(请参阅)。我的答案是一般的,而不是Android SDK专用的。如果有更方便的api,请不要重新发明方向盘并付诸实践:]感谢您向我介绍GSON,它看起来像是一个很好的库,不再需要我的al函数
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;
}