【发布时间】:2016-08-02 19:45:49
【问题描述】:
我有以下统一的方法将JSONArrays 转换成Java 数组。我承认它看起来并不像应有的那么好,但 AFAICT 这是大多数 Java 泛型可以承担这项任务的能力。
@SuppressWarnings("unchecked")
public static <T> T[] getArray(JSONArray array, Class<T> clazz)
{
if(array == null) return null;
int nfiles = array.length();
if(nfiles == 0) return null;
T result[] = (T[]) Array.newInstance(clazz, nfiles);
for(int j = 0; j < nfiles; j++)
{
try
{
T vv = (T)array.get(j); // temp variable for investigation, type T
// assigment passes without an exception!
if(vv.getClass() != clazz) // outputs "java.lang.Integer!=java.lang.Long"
{
LOG(vv.getClass().getName() + "!=" + clazz.getName());
}
// Next line throws ArrayStoreException
result[j] = vv; // Integer cannot be stored in an array of type Long[]
}
catch(JSONException e)
{
e.printStackTrace();
result[j] = null;
}
}
return result;
}
可以这样使用(这只是一个例子,在真正的代码中输入数组来自分层的 JSON 结构):
Integer a[] = getArray(new JSONArray("[15,16]"), Integer.class);
在我偶然发现一个应该是Long 类型的数组之前,它似乎工作了一段时间。该方法失败,ArrayStoreException: java.lang.Integer cannot be stored in an array of type java.lang.Long[] 在线,在代码中做了相应的标记。
嗯,我知道JSONArray.get() 方法返回Object,它包含JSON 库认为适合当前输入的任何类型。如果它看到像“[15,16]”这样的数组,它会将类型推断为Integer。问题是带有 temp 变量的行应该在参数化后读取:
Long vv = (Long)array.get(j);
就get()返回Integer而言,这是应该抛出类型转换异常或将Integer实例转换为Long实例的行,如果它是安全的,我认为。取而代之的是,临时变量的类型动态更改为Integer,这由日志输出确认,然后代码才会在尝试将此Integer 存储到准备好的Longs 数组时中断。 /p>
其实我可以通过这样的代码轻松解决这个问题:
if(clazz == Long.class)
{
vv = array.getLong(j);
}
但这正是我写这个方法的原因,希望泛型可以为我处理这个问题:它的目的是消除对不同类型的许多条件检查和对特定方法的调用,例如getBoolean, getString等
谁能解释一下这里发生了什么以及如何修复代码以使其尽可能简单和统一?
顺便说一句,我没有找到一种方法来编写一个长数字作为 JSONObject 和 JSONArray 被识别为 Long 的输入文字。例如,输入“[15L,16L]”经过JSONArray解析后生成Strings ["15L", "16L"]的Java数组。我错过了什么吗?
【问题讨论】:
标签: java android json generics type-conversion