2017-05-08 62 views
1

我正在使用GSON来解析Java中的json。当我想从一个JSON字符串的整数列表,我的代码看起来是这样的:找出GSON的TypeToken是否包含列表?

Type type = new TypeToken<List<Integer>>(){}.getType(); 

    List<Integer> result = null; 
    try { 
     result = new Gson().fromJson(jsonStringGoesHere, type); 
    } catch (JsonSyntaxException e) { 
     e.printStackTrace(); 
    } 

如果jsonStringGoesHere是一个空字符串或NULL,result也为空。

但是,如果Collection的值等于null,这被认为是不好的做法,所以我宁愿在这种情况下有一个空的List而不是null。

所以基本上这就是我想现在要做的:如果result是空的,我要检查,如果typeList(或List亚型)。如果为true,我会使结果成为一个空ArrayList。我如何检查type是否包含ListList的子类型?

我的尝试是检查if(type instanceof Collection) - 但返回false。

我的下一个尝试是采取type.getTypeName()它返回字符串java.util.List<java.lang.Integer>,并试图从创建一个对象:

 Class c = Class.forName(type.getTypeName()); 
     Object o = c.newInstance(); 
     if(o instanceof List){ 
      System.out.println("it's working!"); 
     } 

但这抛出​​。

任何想法如何使这项工作?

+0

将List更改为ArrayList中的Type Type = new TypeToken >(){}。getType();'。检查http://stackoverflow.com/questions/4818228/how-to-instantiate-a-java-util-arraylist-with-generic-class-using-reflection – Ibrahim

+0

@Ibrahim这样做,'结果'仍为空,'' instanceof'仍然返回false,并且创建newInstance()仍会抛出java.lang.ClassNotFoundException:java.util.ArrayList 。 – user2015253

回答

1

我试图检查if(type instanceof Collection) - 但返回false

这不会起作用,因为TypeCollection不是“相互浇注料”,并在不同的层次存在。

我的下一个尝试是采取type.getTypeName()它返回字符串java.util.List<java.lang.Integer>

这将不能工作。 Class.forName通过完全限定名称(简单来说,文件在CLASSPATH中表示的内容)返回现有的Class<?>实例,但从未 - 参数化类(类不是可参数化的类,但可以是具有参数化超类的子类 - 这就是在类型令牌的引擎下)。因此,Class.forName("java.util.List")是有道理的,但Class.forName("java.util.List<String>")没有。

注意Type的东西,可以代表一个类型TypeToken<T>服务于这个目的。只要看看它是如何声明的 - 你会更好地理解它。更多的是,其子接口ParameterizedType可以保存类型参数,这可以通过TypeToken生成,或者手动构建(像往常一样 - 只需看看接口声明)。 TypeToken通常使用匿名基类参数化来获取类型参数,这就是为什么它们是这样设计的:良好的编译时支持+在Google Guava,Jackson,Spring Framework中有类似的技术(但它会很好如果Java可以支持类似java.util.List<Integer>.type来获取参数化类型实例)。从后面的Gson版本开始,您甚至可以使用TypeToken.getParameterized(...)这只是一种简便的方法来创建参数化类型。

您要找的是“class-instanceof”或“a-subclass-of”(如果可以这样称呼它):Class.isAssignableFrom(...)。此实例方法检查一个类是否相同或另一个类的子类。说,

SuperClass.class.isAssignableFrom(SubClass.class) 

总是返回true。所以,你只需要检查是这样的:

final Type type = new TypeToken<List<Integer>>() { 
}.getType(); 
final TypeToken<?> typeToken = TypeToken.get(type); 
System.out.println(List.class.isAssignableFrom(typeToken.getRawType())); 

或者更短:

final TypeToken<List<Integer>> typeToken = new TypeToken<List<Integer>>() { 
}; 
System.out.println(List.class.isAssignableFrom(typeToken.getRawType())); 

两个返回true。需要注意的是类型令牌通过getRawType()回到Class<?>实例,但不getType()因为后者可能代表不是一类(比方说,会是什么Collection<String>.class.isAssignableFrom(List<Integer.class>)回报呢?)

此外,您还可以提取类型标记及其类型static final领域,因为它们是意味着不可改变的值,并且不应在运行时更改。

0

在Java中Java的泛型部分在编译时发挥作用,因此它在运行时不可用,这就是您得到该异常的原因。所以如果你想创建类收集类型使用反射,那么你必须删除通用部分。

而且列表设置地图是它们不能被直接实例化接口。因此,为了创建一个对象,你必须使用其实施的一个,像ArrayList中LinkedList的

相关问题