Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/386.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 使用泛型返回具有类型参数的对象并避免类型安全警告_Java_Generics - Fatal编程技术网

Java 使用泛型返回具有类型参数的对象并避免类型安全警告

Java 使用泛型返回具有类型参数的对象并避免类型安全警告,java,generics,Java,Generics,我正在编写一个类,该类为我的环境提供一些通用工具 在这个类中,我使用以下方法接收JSON字符串,并将JSON映射到适当的对象: public static <T> T mapJsonToObject(String json, Class<T> clazz) { ObjectMapper mapper = new ObjectMapper(); T parsedObject = null; try { parsedObject = m

我正在编写一个类,该类为我的环境提供一些通用工具

在这个类中,我使用以下方法接收JSON字符串,并将JSON映射到适当的对象:

public static <T> T mapJsonToObject(String json, Class<T> clazz) {
    ObjectMapper mapper = new ObjectMapper();
    T parsedObject = null;
    try {
        parsedObject = mapper.readValue(json, clazz);
    } catch (Exception e) {
        e.printStackTrace();
    }
    return parsedObject;
}
他们都工作正常

但是,如果我不想将JSON映射到特定对象,而只想使用键/值对将其转换为映射,如下所示:

HashMap<String, Object> myMap = MyUtilities.mapJsonToObject(result, HashMap.class);
HashMap-myMap=MyUtilities.mapJsonToObject(结果,HashMap.class);
我从编译器得到一个
“类型安全:HashMap类型的表达式需要未经检查的转换以符合HashMap”
警告。这是因为我在使用HashMap.class时丢失了泛型参数

在写这个问题时,我实际上偶然发现了教程,并想到了用以下方式重载映射方法:

public static <T> T mapJsonToObject(String json, T obj) {
    ObjectMapper mapper = new ObjectMapper();
    T parsedObject = null;
    try {
        parsedObject = mapper.readValue(json, new TypeReference<T>() {});
    } catch (Exception e) {
            e.printStackTrace();            
    }
    return parsedObject;
}
publicstatictmapjsontoobject(字符串json,tobj){
ObjectMapper mapper=新的ObjectMapper();
T parsedObject=null;
试一试{
parsedObject=mapper.readValue(json,newTypeReference(){});
}捕获(例外e){
e、 printStackTrace();
}
返回parsedObject;
}
这需要传递一个我更愿意避免的实际对象:

HashMap<String, Object> myMap = null;
myMap = MyUtilities.mapJsonToObject(result, myMap);
HashMap myMap=null;
myMap=MyUtilities.mapJsonToObject(结果,myMap);

你知道如何改进这两种方法以避免物体通过和类型安全警告吗?请注意,我并不是在寻找一种针对HashMap的解决方案,它使用的是泛型类型,您将始终面临类型擦除问题。作为一种解决方法,您可以执行取消选中的类型转换,如下所示:

@SuppressWarnings("unchecked")
public static <C, T extends C> C mapJsonToObject(String jsonString, Class<T> result) {
    // ... stuff ...
    return (C) parsedObject;
}
@SuppressWarnings(“未选中”)
公共静态C mapJsonToObject(字符串jsonString,类结果){
//…东西。。。
返回(C)parsedObject;
}
但是,考虑到您无法控制Jackson将实际使用哪些类作为集合项,这是非常糟糕的

为了获得更好的效果,您可以使用Jackson的:

@SuppressWarnings(“未选中”)
公共静态C mapJsonToObject(字符串jsonString,JavaType){
//…东西。。。
返回(C)parsedObject;
}
//检查关于TypeFactory#collectionType弃用的答案注释
列表结果=mapJsonToObject(“[]”,TypeFactory.collectionType(ArrayList.class,MyBean.class));
或者你可以使用杰克逊的:

publicstatictmapjsontoobject(字符串jsonString,TypeReference类型){
//…东西。。。
}
列表结果=mapJsonToObject(“[]”,新类型引用(){});
我有点喜欢第一种方法(通过JavaType),因为它不会为您编写的每个方法调用创建匿名类


更新为什么第一个选项难看:

第一个选项有效,因为通用参数
T
C
之间的关系接近于零。当根据传递的参数推断出
T
时,将根据结果赋值推断出
C
。它们之间唯一的限制是
T
必须扩展
C
。这只是一种防止完全错误调用的形式,如
String s=mapJsonToObject(“,List.class)

这个选项很难看,因为你没有提到地图的内容。也就是说,由Jackson决定要使用哪种类型的课程

例如,
{“foo”:“xxx”,“bar”:1}
可能会使用以下条目映射到映射:

  • 字符串“foo”=>字符串“xxx”
  • 字符串“bar”=>整数1
但是对于
{“foo”:{“bar”:1}
它可能是这样的:

@SuppressWarnings("unchecked")
public static <C, T extends C> C mapJsonToObject(String jsonString, Class<T> result) {
    // ... stuff ...
    return (C) parsedObject;
}
  • 字符串“foo”=>ObjectNode
    {“bar”:1}

您可以使用第一个选项。但是,除了
Map
和没有嵌套对象或数组的简单JSON字符串之外,它永远不会有任何用处。

oh-wow!第一个选项实际上是有效的。怎样?你能详细解释一下为什么它可能不好吗?其他两个选项是更好的练习,但我希望避免在该实用程序类之外使用Jackson,这也是我首先包装此方法的原因。@dagandlerx添加了关于第一个选项的一些附加信息。谢谢,这个解释确实有助于总结第二个代码示例中使用的
TypeFactory.collectionType
静态方法在Jackson 1.8中被弃用,后来被删除。当前的等价物似乎是从
ObjectMapper
的配置中获取
TypeFactory
实例,并在其上调用
constructCollectionType
mapper.getDeserializationConfig().getTypeFactory().constructCollectionType(ArrayList.class,MyBean.class)。在示例中添加了注释。非常感谢。
@SuppressWarnings("unchecked")
public static <C> C mapJsonToObject(String jsonString, JavaType type) {
    // ... stuff ...
    return (C) parsedObject;
}

// Check answer comments on TypeFactory#collectionType deprecation
List<MyBean> result = mapJsonToObject("[]", TypeFactory.collectionType(ArrayList.class, MyBean.class));
public static <T> T mapJsonToObject(String jsonString, TypeReference<T> type) {
    // ... stuff ...
}

List<MyBean> result = mapJsonToObject("[]", new TypeReference<List<Object>>() {});