当前位置: 首页 > 知识库问答 >
问题:

为什么这段代码包装在泛型函数中不起作用?

叶坚
2023-03-14

我使用以下代码执行HTTP POST请求并反序列化返回的值:

ParameterizedTypeReference<MyClass> typeRef = new ParameterizedTypeReference<>() {};
HttpEntity<Object> requestEntity = new HttpEntity<>("some text");
ResponseEntity<MyClass> result = restTemplate.exchange("/test", HttpMethod.POST, requestEntity, typeRef);
MyClass returnValue = result.getBody();

为了让它更容易使用,我尝试将代码封装在一个函数中,如下所示:

public <T> T post(Object content, Class<T> returnType, String url){
    ParameterizedTypeReference<T> typeRef = new ParameterizedTypeReference<>() {};
    HttpEntity<Object> requestEntity = new HttpEntity<>(content);
    ResponseEntity<T> response = restTemplate.exchange(url, HttpMethod.POST, requestEntity, typeRef);
    return response.getBody();
}

然而,当代码被放入函数中时,它就会停止工作。它抛出java.lang.ClassCastException:java.base/java.util.LinkedHashMap不能强制转换为client.rest.MyClass。似乎有些类型信息在途中丢失了。

package client.rest;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.BeforeClass;
import org.junit.Test;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.http.*;
import org.springframework.test.web.client.MockRestServiceServer;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.client.support.RestGatewaySupport;

import static org.springframework.test.web.client.ExpectedCount.times;
import static org.springframework.test.web.client.match.MockRestRequestMatchers.requestTo;
import static org.springframework.test.web.client.response.MockRestResponseCreators.withSuccess;

class MyClass {
    public int getInt(){
        return 1;
    }

    public void setInt(int i){}
}

public class TEMP {

    public static RestTemplate restTemplate = new RestTemplate();
    public static MockRestServiceServer mockServer;

    @BeforeClass
    public static void beforeClass() throws JsonProcessingException {
        MyClass value = new MyClass();

        // set up a mock server
        RestGatewaySupport gateway = new RestGatewaySupport();
        gateway.setRestTemplate(restTemplate);
        mockServer = MockRestServiceServer.bindTo(gateway).build();

        ObjectMapper objectmapper = new ObjectMapper();
        String payload = objectmapper.writeValueAsString(value);

        mockServer.expect(times(2), requestTo("/test"))
            .andRespond(withSuccess(payload, MediaType.APPLICATION_JSON));
    }

    @Test
    public void without_function() {
        ParameterizedTypeReference<MyClass> typeRef = new ParameterizedTypeReference<>() {};
        HttpEntity<Object> requestEntity = new HttpEntity<>("some text");
        ResponseEntity<MyClass> result = restTemplate.exchange("/test", HttpMethod.POST, requestEntity, typeRef);
        MyClass returnValue = result.getBody();
    }

    public <T> T post(Object content, Class<T> returnType, String url){
        ParameterizedTypeReference<T> typeRef = new ParameterizedTypeReference<>() {};
        HttpEntity<Object> requestEntity = new HttpEntity<>(content);
        ResponseEntity<T> response = restTemplate.exchange(url, HttpMethod.POST, requestEntity, typeRef);
        return response.getBody();
    }

    @Test
    public void with_function() {
        MyClass returnValue = post("some text", MyClass.class, "/test");
    }
}
    null

共有1个答案

沃弘图
2023-03-14

1的答案。

ParameterizedTypeReference<X> typeRef = new ParameterizedTypeReference<X>() {};

感谢最后的{}jackson能够使用反射找出X在运行时是什么,但是X是在编译时解析的,所以如果您有MyClassT,这正是它在运行时将得到的;它将无法确定t在运行时被分配给什么。

出于同样的原因,如果您继续使用function-less选项,但在最后删除{},它将编译,但将导致相同的错误。

@Test
    public void with_function() {
        ParameterizedTypeReference<MyClass> typeRef = new ParameterizedTypeReference<>() {}; 
        MyClass returnValue = post("some text", typeRef, "/test");
    }
}

但是,我认为您应该考虑不依赖{}技巧的替代方案,这可能会有问题。

您是否尝试过ParameterizedTypeReferencefortype?:

public <T> T post(Object content, Class<T> returnType, String url){
        ParameterizedTypeReference<T> typeRef = ParameterizedTypeReference.forType(returnType);
        HttpEntity<Object> requestEntity = new HttpEntity<>(content);
        ResponseEntity<T> response = restTemplate.exchange(url, HttpMethod.POST, requestEntity, typeRef);
        return response.getBody();
}

在任何情况下,这都将处理对t的非泛型赋值,比如myclass,就像将myclass.class作为返回类型传递时一样;它不能用于ArrayList 列表;List.getClass() ,因为它相当于返回ArrayList.class。我想在这些情况下,您需要构造并传递一个不同的type实例,该实例对应于更复杂的类型表达式。

 类似资料:
  • 因此,下面的代码,从txt文件中取序列号作为参数,在我的计算机上正常工作。每个数字都写在一行上。下面是代码: 但它在CodeEval中不起作用。站点编译器是这么说的: Fontconfig错误:无法加载默认配置文件线程“main”java.awt.HeadLessException:未设置X11显示变量,但此程序执行了需要它的操作。在java.awt.GraphicsEnvironment.Che

  • 关于如何修复gradle版本,有很多很好的建议,但有些已经过时了,或者我只是找不到建议的路径。对我来说,一个解决方案是Project>Project Structure>Project>Gradle Version。 在这里我可以把它改成支持的版本,并且成功地构建项目。 从这个链接,它暗示这是设置你的gradle包装的方式。 因此,我希望Project/Platforms/Android/Grad

  • 我试图制作一个简单的程序来查找列表的模式,但它只是抛出了范围外错误的索引。 谢谢

  • (下面是完整的代码)我刚刚交了一个课堂实验,在那里我们必须做一个描述某本书的课堂。我不知道怎么做两件事。1.如果有人为“页面”或“SuggestedMetalPrice”输入的值小于零,则该值必须设置为零。在该代码中,即使值为正,该值也设置为0。在: 如果我将第二个“0”设置为不同的数字,比如说: 那么你输入的“页面”的值将是1。但是如果你输入的值是负数,它不应该只有1吗?我不明白我做错了什么。

  • 导致上述语句中问题的代码

  • 问题内容: 码: 上面的代码不起作用。当我单击#clicker时,它不会发出警报,也不会隐藏。我检查了控制台,没有任何错误。我还检查了JQuery是否正在加载,实际上是否正在加载。所以不确定是什么问题。我还执行了带有警报的文档就绪功能,并且该功能正常工作,因此不确定我在做什么错。请帮忙。谢谢! 问题答案: 您应该在一个块中添加javascript代码。 即 正如jQuery文档指出的那样:“在文档