具有泛型的命令对象(Command Object with generics)

编程入门 行业动态 更新时间:2024-10-17 17:26:59
具有泛型的命令对象(Command Object with generics)

我有一个控制器,它有一个使用泛型的Command Object ,如下所示:

@Controller @RequestMapping(value = "/first") public class MyFirstController { @RequestMapping(value = "/something", method = RequestMethod.POST) @ResponseBody public ADifferentDTO doSomething(RequestDTO<MyStringObject> requestDTO, HttpServletRequest request, HttpServletResponse response) { requestDTO.getSomeObject(); // ERROR HERE //.. do something } }

但是,这不起作用。 由于Java中的Type Erasure,我认为它不起作用。 有没有办法让Command对象使用泛型? 以下是其他一些类的外观。

public class RequestDTO<T> { private T someObject; // some other objects here as well that are from a submitted form (not listed) public void setSomeObject(T someObject){ this.someObject = someObject; } public T getSomeObject(){ return someObject; } } public class MyStringObject { private String someString; public MyStringObject(String someString){ this.someString = someString; } // getter and setter } public class MyIntegerObject { private Integer someInteger; private Integer anotherInteger; public MyIntegerObject(Integer someInteger, Integer anotherInteger){ this.someInteger = someInteger; this.anotherInteger = anotherInteger; } // getter and setter }

我得到的错误:

java.lang.Object cannot be cast to com.test.MyStringObject

当然,如果我将RequestDTO更改为仅使用MyStringObject它可以正常工作。

public class RequestDTO { private MyStringObject someObject; // some other objects here as well that are from a submitted form (not listed) public void setSomeObject(MyStringObject someObject){ this.someObject = someObject; } public MyStringObject getSomeObject(){ return someObject; } }

有没有办法可以做到这一点?

I have a controller that has a Command Object that uses generics like so:

@Controller @RequestMapping(value = "/first") public class MyFirstController { @RequestMapping(value = "/something", method = RequestMethod.POST) @ResponseBody public ADifferentDTO doSomething(RequestDTO<MyStringObject> requestDTO, HttpServletRequest request, HttpServletResponse response) { requestDTO.getSomeObject(); // ERROR HERE //.. do something } }

However, this does not work. I'm assuming it does not working because of Type Erasure in Java. Is there a way I can have the Command Object use a generic? Here is what some of the other classes might look like.

public class RequestDTO<T> { private T someObject; // some other objects here as well that are from a submitted form (not listed) public void setSomeObject(T someObject){ this.someObject = someObject; } public T getSomeObject(){ return someObject; } } public class MyStringObject { private String someString; public MyStringObject(String someString){ this.someString = someString; } // getter and setter } public class MyIntegerObject { private Integer someInteger; private Integer anotherInteger; public MyIntegerObject(Integer someInteger, Integer anotherInteger){ this.someInteger = someInteger; this.anotherInteger = anotherInteger; } // getter and setter }

The error I get:

java.lang.Object cannot be cast to com.test.MyStringObject

Of course if I change my RequestDTO to only use a MyStringObject it works fine.

public class RequestDTO { private MyStringObject someObject; // some other objects here as well that are from a submitted form (not listed) public void setSomeObject(MyStringObject someObject){ this.someObject = someObject; } public MyStringObject getSomeObject(){ return someObject; } }

Is there a way this can be done?

最满意答案

你是对的,这是因为类型擦除。

可能最简单的解决方案是创建一个RequestDTO子类,使用每个My * Object参数化并将其用作命令对象类。

举个例子:

@SpringBootApplication public class So44423504Application { public static void main(String[] args) { SpringApplication.run(So44423504Application.class, args); } @RestController @RequestMapping(value = "/first") public static class MyFirstController { public static class MyStringRequestDTO extends RequestDTO<MyStringObject> {} public static class MyIntegerRequestDTO extends RequestDTO<MyIntegerObject> {} @PostMapping(value = "/something") public String doSomething(@ModelAttribute MyStringRequestDTO/*MyIntegerRequestDTO*/ requestDTO) throws JsonProcessingException { return new ObjectMapper().writeValueAsString(requestDTO); } } public static class RequestDTO<T> { private T someObject; // getter and setter } public static class MyStringObject { private String someString; public MyStringObject() { } // required since another non-default ctor is present. public MyStringObject(String someString){ this.someString = someString; } // getter and setter } public static class MyIntegerObject { private Integer someInteger; private Integer anotherInteger; public MyIntegerObject() { } // required since another non-default ctor is present. public MyIntegerObject(Integer someInteger, Integer anotherInteger){ this.someInteger = someInteger; this.anotherInteger = anotherInteger; } // getters and setters } }

然后它工作正常:

$ curl -XPOST 'localhost:8080/first/something?someObject.someInteger=23&someObject.anotherInteger=42' {"someObject":{"someInteger":23,"anotherInteger":42}}% $ curl -XPOST 'localhost:8080/first/something?someObject.someString=test' {"someObject":{"someString":"test"}}%

You are correct, it is because of type erasure.

Probably the simplest solution is to create a RequestDTO subclasses parameterized with each of your My*Object and use it as a Command Object class.

Given your example:

@SpringBootApplication public class So44423504Application { public static void main(String[] args) { SpringApplication.run(So44423504Application.class, args); } @RestController @RequestMapping(value = "/first") public static class MyFirstController { public static class MyStringRequestDTO extends RequestDTO<MyStringObject> {} public static class MyIntegerRequestDTO extends RequestDTO<MyIntegerObject> {} @PostMapping(value = "/something") public String doSomething(@ModelAttribute MyStringRequestDTO/*MyIntegerRequestDTO*/ requestDTO) throws JsonProcessingException { return new ObjectMapper().writeValueAsString(requestDTO); } } public static class RequestDTO<T> { private T someObject; // getter and setter } public static class MyStringObject { private String someString; public MyStringObject() { } // required since another non-default ctor is present. public MyStringObject(String someString){ this.someString = someString; } // getter and setter } public static class MyIntegerObject { private Integer someInteger; private Integer anotherInteger; public MyIntegerObject() { } // required since another non-default ctor is present. public MyIntegerObject(Integer someInteger, Integer anotherInteger){ this.someInteger = someInteger; this.anotherInteger = anotherInteger; } // getters and setters } }

Then it works fine:

$ curl -XPOST 'localhost:8080/first/something?someObject.someInteger=23&someObject.anotherInteger=42' {"someObject":{"someInteger":23,"anotherInteger":42}}% $ curl -XPOST 'localhost:8080/first/something?someObject.someString=test' {"someObject":{"someString":"test"}}%

更多推荐

本文发布于:2023-07-26 00:24:00,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1268395.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:命令   对象   Command   Object   generics

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!