简体   繁体   English

如何将通用类作为方法的通用参数传递

[英]How to pass generic class as a generic parameter of method

I have a problem with passing class as a generic param of the method, fe I have a simple method: 我有一个将类作为方法的泛型参数传递的问题,如果我有一个简单的方法:

<T> T sendRequest(SomeRestApiRequest request, Class<T> responseClass)

which parsing response to specified form. 解析对指定形式的响应。 I use them in this way: 我以这种方式使用它们:

ItemListJSON itemList = new ItemListJSON();
itemList = someRestClient.sendRequest(req, ItemListJSON.class);

for ItemListJSON.class which look like that: 用于ItemListJSON.class,如下所示:

@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonPropertyOrder({"totalSize","items"})
public class ItemListJSON {

    @JsonProperty("items")
    private List<SalonJSON> items;

    @JsonProperty("totalSize")
    private int totalSize;

    //...getters, setters...
}

and everything's fine. 一切都很好。 But my question is: 但是我的问题是:

Is it possible to pass generic class as an argument of sendRequest method? 是否可以将通用类作为sendRequest方法的参数传递

I want that ItemListJSON class is generic, in my case: 在我的情况下,我希望ItemListJSON类是通用的:

@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonPropertyOrder({"totalSize","items"})
public class ItemListJSON<T> {

    @JsonProperty("items")
    private List<T> items;

    @JsonProperty("totalSize")
    private int totalSize;

    //...getters, setters...
}

But when I was trying use sendRequest method in this way: 但是当我尝试以这种方式使用sendRequest方法时:

ItemListJSON<SalonJSON> itemList = new ItemListJSON<SalonJSON>();
itemList = someRestClient.sendRequest(req, ItemListJSON.class);

I got warning on Eclipse IDE 我在Eclipse IDE上收到警告

Type safety: The expression of type ItemListJSON needs unchecked conversion to conform to ItemListJSON 类型安全:类型为ItemListJSON的表达式需要未经检查的转换才能符合ItemListJSON

and when method was called i got error in server console: 当调用方法时,服务器控制台出现错误:

SEVERE: Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is java.lang.ClassCastException: java.util.LinkedHashMap cannot be cast to xxx.ServiceCategoryJSON] with root cause
java.lang.ClassCastException: java.util.LinkedHashMap cannot be cast to xxx.ServiceCategoryJSON

@EDIT: @编辑:

I debbuged my sendRequest method and I found that error occurs in processResponse method, where is mapping response to object by ObjectMapper. 我调试了sendRequest方法,发现在processResponse方法中发生错误,该方法通过ObjectMapper将响应映射到对象。

private <T> T processResponse(Response response, Class<T> responseClass) throws ParseException, IOException {
        ObjectMapper om = new ObjectMapper();
        om.enable(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY);     
        return om.readValue(response.getBody(), responseClass); //throw exception
    }

Use 采用

ParameterizedTypeReference<ItemListJSON<SalonJSON>> typeRef = new ParameterizedTypeReference<ItemListJSON<SalonJSON>>() {};

See the code snipped from the rest template intro 查看其余模板介绍中的代码

RestTemplate restTemplate = new RestTemplate();
ParameterizedTypeReference<List<String>> listOfString = new ParameterizedTypeReference<List<String>>() {};
ResponseEntity<List<String>> response= restTemplate.exchange(baseUrl,HttpMethod.GET,null, listOfString);
HttpHeaders headers = response.getHeaders();
MediaType contentType = headers.getContentType();
long date = headers.getDate();
List<String> getOrDefault = headers.getOrDefault("X-Forwarded", Collections.singletonList("Does not exists"));

You can do this that way by passing com.fasterxml.jackson.core.type.TypeReference instead of Class<T> 您可以通过传递com.fasterxml.jackson.core.type.TypeReference而不是Class<T>

public class GenericSerializationTest {

    @Data //lombok
    public static class ItemListJSON<T> {
        private List<T> items;
    }

    @Data //lombok
    public static class StructureExample {
        private final String name;
        private final Double price;
    }

    public static class Sender {
        private final ObjectMapper objectMapper = new ObjectMapper();

        public <T> T sendRequest(String json, TypeReference typeReference) throws IOException {
            //sender logic - in this case I assume that json is API response
            return objectMapper.readValue(json, typeReference);
        }
    }

    @Test
    public void testMethod() throws IOException {
        Sender sender = new Sender();
        ItemListJSON<StructureExample> test = sender.sendRequest("{\"items\": [{\"name\":\"MacBook Pro\",\"price\":101.345}, {\"name\":\"MacMini\",\"price\":102.345}]}", new TypeReference<ItemListJSON<StructureExample>>() {});

        assertEquals("Should contain only 2 items", 2, test.getItems().size());
        assertEquals("Name of first item is not correct", "MacBook Pro", test.getItems().get(0).getName());
        assertEquals("Name of second item is not correct", "MacMini", test.getItems().get(1).getName());
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM