使用 ModelMapper 映射扩展泛型类型的字段时出现 ClassCastException

问题描述 投票:0回答:1

我有以下类结构(代码在最后):

  • abstract class AbstractThing
    :我有一些具有共同领域的不同种类的东西
  • class Foo extends AbstractThing
    :foo 是一种东西
  • abstract class AbstractReq <T extends AbstractThing>
    :我有与事物相关的请求,其中请求的主题是一个字段 (
    T subject
    )
  • FooReq extends AbstractReq<Foo>
    :关于 foos 的请求,特别是
  • FooReqDto
    :一个 DTO 类,所有字段都在
    FooReq
    中,扁平化

我正在尝试使用 ModelMapper 将

FooReq
的实例映射到
FooReqDto
。如果我不需要自定义类型映射,那么一切都会很好。但我确实(在我的实际代码中)需要自定义一些东西,由名为
somethingDifferent
的字段表示,而不是
subjectFooField
中的
FooReqDto
。现在,当我运行测试时,出现以下错误:

java.lang.ClassCastException:类 com.example.test.TempTest$AbstractThing$ByteBuddy$PsTTXfw5 无法转换为类 com.example.test.TempTest$Foo (com.example.test.TempTest$AbstractThing$ByteBuddy$PsTTXfw5 和com.example.test.TempTest$Foo 位于加载程序“app”的未命名模块中)

创建类型映射时我缺少什么?涉及继承和泛型的映射类似乎不存在任何固有的问题,因为它在没有映射的情况下工作。在我提取抽象类之前,我使用的实际映射工作得很好(这对于减少大量重复代码是必要的)。

完整代码如下:

package com.example.test;

import org.junit.Test;
import org.modelmapper.ModelMapper;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

public class TempTest {

    @Test
    public void testStuff() {
        final ModelMapper mapper = new ModelMapper();
        mapper.createTypeMap(FooReq.class, FooReqDto.class)
                .addMappings(map -> {
                    map.map(req -> req.getSubject().getFooField(), FooReqDto::setSomethingDifferent);
                });
        final FooReq req = new FooReq();
        req.setSubmitted(true);
        req.getSubject().setName("testFoo");
        req.getSubject().setFooField("bar");
        final FooReqDto dto = mapper.map(req, FooReqDto.class);
        assertTrue(dto.isSubmitted());
        assertEquals("testFoo", dto.getSubjectName());
        assertEquals("bar", dto.getSomethingDifferent());
    }

    public static abstract class AbstractThing {
        private String name;

        // getters and setters omitted
    }

    public static class Foo extends AbstractThing {
        private String fooField;

        // getters and setters omitted
    }

    public static abstract class AbstractReq <T extends AbstractThing> {
        protected T subject;
        private boolean submitted;

        // getters and setters omitted
    }

    public static class FooReq extends AbstractReq<Foo> {
        public FooReq() {
            super();
            subject = new Foo();
        }
    }

    public static class FooReqDto {
        private boolean submitted;
        private String subjectName;
        private String somethingDifferent;

        public FooReqDto() {

        }

        // getters and setters omitted
    }
}

java modelmapper
1个回答
0
投票

对此的一个快速解决方法是向

FooReq
添加显式设置器:

public static class FooReq extends AbstractReq<Foo> {
    public FooReq() {
        super();
        subject = new Foo();
    }
    public Foo getSubject() { return subject; }
    public void setSubject(Foo subject) { this.subject = subject; }
}

它对于父 getter 和 setter 来说是多余的,但可以防止 ModelMapper 在使用反射时感到困惑并在运行时丢失通用信息。

如果父类的唯一目标是减少模型类本身的重复,那么这基本上会达不到目的。就我而言,此设置是一个工具,因此我可以完成其他事情,因此此解决方案适合我。不过,我有兴趣看到仅通过调整 ModelMapper 配置即可工作的其他选项。

© www.soinside.com 2019 - 2024. All rights reserved.