通过Java上的参数获取类型

时间:2012-12-30 20:59:44

标签: java generics gson

当然,我在所有这些Java中都很新,所以我有一个问题,我试图反序列化在WCF服务上获得的响应,一切正常,但是,我是试图制作一个通用函数来做到这一点。

基本上我做的是

public List<msg> GetService(String method){
    List<msg> response = new ArrayList<msg>();

    Type msgType = new TypeToken<List<msg>>(){}.getType();

    //Obtaining result
    response = uJSON.fromJson(serviceResponse, msgType);
    //uJSON is an instance of Gson library, for deserializing it just needs
    //the service response and a Class<T> or Type to reflect the obtained message
}

我想要做的就是获得Type&#34; msg&#34;通用,这意味着......

public <thing> void GetInstanceService(String method){
     List<thing> response = new ArrayList<thing>();

     Type rType2 = new TypeToken<List<thing>>(){}.getType(); //Got java.util.List<thing>

     //And when I'm trying to deserialize I just obtain a List of object 
     //[java.lang.Object@5c7a987e, java.lang.Object@74b1a7a0]

     type2 = uJSON.fromJson(new String(entity), rType2);
}

但我这样打电话。

comm.<msgType>GetInstanceService("listTestType");

所以,当我打电话给&#34; GetInstanceService&#34;,&#34; thing&#34;是&#34; msgType&#34;输入,为 List<thing>而且回复不应该是List<msgType>而不是List <Object>

此外,当我尝试通过&#34; Type&#34;明确传递类型时。参数,它只会导致我这样的编译时错误。

public void GetInstanceService(Type type){
    List<type> type2 = new ArrayList<type>();  //Compilation time error

    //Or
    msgType oType = new msgType();
    Class classType = oType.getClass();
    List<classType> type3;    //Compilation time error
}

因此,如果这些尝试都没有效果,我怎样才能设置反序列化的类型?

2 个答案:

答案 0 :(得分:3)

Guava类TypeToken不支持该使用模式。您正在使用类型变量创建类型标记,但没有足够的信息可以从List<String>重建List<T>。您应该创建一个TypeToken实例,其中包含所有必需的编译时信息。

文档说:

  

请注意,实际类型参数由a携带至关重要   子类。以下代码是错误的,因为它只捕获<T>   listType()方法签名的类型变量;而<String>是   丢失在擦除中:

class Util {
  static <T> TypeToken<List<T>> listType() {
    return new TypeToken<List<T>>() {};
  }
}

TypeToken<List<String>> stringListType = Util.<String>listType();

但如上所述,您可以在呼叫站点实例化TypeToken,其中所有类型信息都可用,然后将其作为参数传递。像这样:

public <thing> void GetInstanceService(String method, TypeToken<List<thing>> token){
     List<thing> response = new ArrayList<thing>();

     Type rType2 = token.getType();

     type2 = uJSON.fromJson(new String(entity), rType2);
}

comm.GetInstanceService("listTestType", new TypeToken<List<msgType>>() {});

<强>更新

Paul Bellora指出,您也可以接受参数TypeToken<thing> token,并在TypeToken<List<thing>>的方法中构建token

public <thing> void GetInstanceService(String method, TypeToken<thing> token) {
     List<thing> response = new ArrayList<thing>();

     Type rType2 = new TypeToken<List<thing>>() {}
         .where(new TypeParameter<thing>() {}, token); // where() binds "thing" to token
         .getType();

     type2 = uJSON.fromJson(new String(entity), rType2);
}

comm.GetInstanceService("listTestType", new TypeToken<msgType>() {});

答案 1 :(得分:2)

由于名为 type erasure 的东西,所需的类对象在运行时不可用。

但是,有一个标准的解决方法:将类型令牌传递给您的方法,如下所示:

public <T> List<T> getService(String method, Class<T> c) {
    // the caller has passed in the class object
    List<T> list = new ArrayList<T>();
    // fill list
    return list;
}