【问题标题】:Obtaining types through parameters on JavaJava上通过参数获取类型
【发布时间】:2012-12-30 20:59:43
【问题描述】:

当然,我对所有这些 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 "msg" 泛型,这意味着......

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");

所以,当我调用“GetInstanceService”时,“thing”是“msgType”类型,对于 List&lt;thing&gt; 并且响应不应该是 List&lt;msgType&gt; 而不是 List &lt;Object&gt;

此外,当我试图通过“类型”参数显式传递类型时,它只会导致我这样的编译时间错误。

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
}

那么,如果这些尝试都无效,我该如何设置反序列化的类型?

【问题讨论】:

  • 请遵循公认的 Java 方法名称约定。 GetInstanceService 应该是 getInstanceService
  • thing 是类还是实例?如果是实例,则不能用作参数化表达式中的参数。
  • 当然,GetInstanceService(Type type) 中的 type 不能在 new ArrayList&lt;type&gt;() 中使用,因为它不是一个类...
  • yair: thing 是一个类,因为我调用了 comm 之类的方法。GetInstanceService("listTestType");

标签: java generics gson


【解决方案1】:

Guava 类TypeToken 不支持这种使用模式。您正在使用类型变量创建类型标记,但没有足够的信息让它从 List&lt;T&gt; 重构 List&lt;String&gt;。您应该创建一个 TypeToken 的实例,其中包含所有必需的编译时信息。

文档说:

请注意,实际类型参数由 子类。下面的代码是错误的,因为它只捕获了&lt;T&gt; listType() 方法签名的类型变量;而&lt;String&gt; 是 丢失在擦除中:

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&lt;thing&gt; token,并在方法内从该 token 构造一个 TypeToken&lt;List&lt;thing&gt;&gt;

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>() {});

【讨论】:

  • 谢谢,一切正常。但我根本不明白为什么如果我将“Class myClass”作为参数传递,我不能只创建“List”。你有线索吗,只是为了知道。
  • Java 中的Class类型的对象是有区别的。 a 类型Type 类型的对象之间的区别同上。类和类型的示例是intStringList&lt;String&gt;Class 对象和Type 对象的示例是int.classString.classnew TypeToken&lt;List&lt;String&gt;&gt;(){}.getType()
  • @No_Name:可以为仅在运行时知道组件的泛型类型创建Type。你必须自己实现一个实现ParameterizedType接口的类。
  • +1 请注意,该方法可以只使用TypeToken&lt;thing&gt;,然后使用where 组成TypeToken&lt;List&lt;thing&gt;&gt;
  • 感谢@PaulBellora,我搜索了那个方法但找不到它:) where 是漂亮的 API。
【解决方案2】:

由于称为类型擦除,您需要的类对象在运行时不可用。

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

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;
}

【讨论】:

  • 好吧,我就是听不懂。如果我通过 Class c,我也不能使用 List,最后,如果我使用“c”反序列化,我也会得到一个对象列表,而不是 msgType 列表。我有什么不匹配的吗? ----------- 我使用 ----------- msgType c =new msgType();... Class classType = (Class) c.getClass();... comm.getService("listTestType", classType);... ----- 然后 ----- List response = new ArrayList() ;... response = (List) uJSON.fromJson(new String(entity), c);... 因为,我不能做 List 或 ArrayList____ 我很抱歉,但编辑没有'不允许空格
  • 以及如何从Class 对象为T 构造Type 对象为List&lt;T&gt;
猜你喜欢
  • 2015-01-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-02-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多