神奇的 beanUtils.copyProperties 目标与源对象属性类型不一致但可以 set 成功

2022-08-02 16:42:02 +08:00
 simonlu9
public class CourseCategoryResponse {

    private String id;
    @ApiModelProperty("分类名称")
    private String name;
    @ApiModelProperty("分类图标")
    private String image;

    @ApiModelProperty("英文名称")
    private String nameEn;

    @ApiModelProperty("子分类")
    private List<CourseCategoryResponse> children;
    @ApiModelProperty("课程列表")
    private List<CourseSimpleResponse> coures;
}

public class Category {

    @Id
    @Column(length = 37)
    @GeneratedValue(generator = "jpa-uuid")
    private String id;

    @ApiParam("主体")
    @Column(length = 32)
    private String subject;


    @ApiParam("分类名称")
    @Column(length = 32)
    private String name;
   
    private List<Category> children;
    
 }
 
 ==========调用代码=====================
 
  PropertyDescriptor propertyDescriptors = BeanUtils.getPropertyDescriptor(CourseCategoryResponse.class,"children");
        CourseCategoryResponse courseCategoryResponse = new CourseCategoryResponse();
        Category category = new Category();
        category.setName("123");
        Category children = new Category();
        children.setName("234");
        category.setChildren(List.of(children));
        PropertyDescriptor source = BeanUtils.getPropertyDescriptor(Category.class,"children");

        Object value = source.getReadMethod().invoke(category);
       propertyDescriptors.getWriteMethod().invoke(courseCategoryResponse,value);
       System.out.println(courseCategoryResponse);
       
       
 打印结果 courseCategoryResponse 的 children 是有值的,我想这个为什么可以 set 进去
2135 次点击
所在节点    Java
7 条回复
simonlu9
2022-08-02 17:09:20 +08:00
set 是可以 set 成功的,但是 get 会报错,json 序列化也是可以看到有值,是个坑
quericy
2022-08-02 19:04:42 +08:00
因为 List 里的泛型擦除了
sLvxq6Ya
2022-08-02 19:12:42 +08:00
对 BeanUtils 不是很熟悉,推测你这个问题应该是因为 Java 的泛型擦除
Java 的泛型只在编译期进行类型检查,而 BeanUtils 的 Set 是通过运行时反射,不需要经过类型检查

所以执行的时候就相当于给 courseCategoryResponse 的 List<Object> children(原本声明要求 List<CourseCategoryResponse>) 赋值了一个 List<Object> (实际上是 List<Category>), set 时都是 List<Object>不会报错,但是 get 时你可能通过指定变量类型做了一个类型转换,就会报错。
xaplux
2022-08-03 08:38:29 +08:00
2 楼正解
lifespy
2022-08-03 14:30:52 +08:00
歪个楼
@ApiParam 和 @ApiModelProperty 有什么区别吗
Saxton
2022-08-03 22:46:17 +08:00
2 楼正解,这就是反射带来的影响
Saxton
2022-08-03 22:48:50 +08:00
另外我不推荐用 beanUtils 来实现对象的拷贝,本身反射是一种非常危险的行为,并不能在编译的时候发现问题,推荐楼主使用 mapStruct ,编译时会自动生成一个 set 方法

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/870257

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX