You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何替换为方法引用的Map代码抛出TypeNotPresentException异常?

Lambda替换为方法引用后触发TypeNotPresentException的原因与解决

问题场景

将Stream的map操作从lambda表达式t->toDTO(t)替换为方法引用this::toDTO后,程序抛出java.lang.TypeNotPresentException,提示Type com.grupoaev.aevgestion.domain.entities.solicitudes.Tecnico not present,但原lambda写法可正常运行。

报错代码

return findTechnician.findWithUser()
                      .stream()
                      .map(this::toDTO)
                      .collect(Collectors.toSet());

错误信息

Method threw 'java.lang.TypeNotPresentException' exception.
Type com.grupoaev.aevgestion.domain.entities.solicitudes.Tecnico not present

相关类代码

private static class TechniciansModel extends LoadableDetachableModel<Collection<TechnicianDatesDTO>> {

        private static final long serialVersionUID = 1L;

        @SpringBean
        private FindTechnician findTechnician;
        @SpringBean
        private FindTechnicalUserAbsences findTechnicalUserAbsences;

        public TechniciansModel() {
            Injector.get().inject(this);
        }

        @Override
        protected Collection<TechnicianDatesDTO> load() {

            return findTechnician.findWithUser()
                          .stream()
                          .map(t->toDTO(t))
                          .collect(Collectors.toSet());
        }

        @NotNull
        private TechnicianDatesDTO toDTO(Tecnico technician) {
            String displayingName = technician.getUsuario().getName();

            Set<Range<LocalDate>> invalidDates =
                    findTechnicalUserAbsences.findByTecnicoId(technician.getId())
                                             .stream()
                                             .map(absence -> new Range<>(toLocalDate(absence.getFechaInicio()),
                                                                         toLocalDate(absence.getFechaFin())))
                                             .collect(Collectors.toSet());

            return new TechnicianDatesDTO(displayingName, invalidDates);
        }

        private LocalDate toLocalDate(Date date) {
            return date != null ? date.toInstant().atZone(ZoneId.systemDefault()).toLocalDate() : null;
        }
    }

原正常运行代码

return findTechnician.findWithUser()
                      .stream()
                      .map(t->toDTO(t))
                      .collect(Collectors.toSet());

原因分析

这是Java类型擦除与方法引用的类型解析机制差异导致的:

  • Lambda表达式在编译时会延迟类型推断,它的参数类型t是在运行时根据Stream的元素类型(findWithUser()的返回类型)确定的,不会在编译阶段强制解析Tecnico类的存在性。
  • 方法引用this::toDTO在编译阶段就会直接关联到toDTO(Tecnico technician)方法,此时JVM会尝试解析方法参数中的Tecnico类。如果该类在编译时类路径存在,但运行时因类加载器问题(如Spring类加载机制、模块化隔离)或类被移除,就会抛出TypeNotPresentException。

解决方法

  1. 保留Lambda写法:Lambda的延迟类型推断避开了类加载时的类型解析问题,直接沿用t->toDTO(t)即可。
  2. 显式指定泛型类型:在map方法中显式指定泛型参数,帮助编译器提前锁定类型,规避方法引用的类型解析异常:
    return findTechnician.findWithUser()
                          .stream()
                          .<TechnicianDatesDTO>map(this::toDTO)
                          .collect(Collectors.toSet());
    
  3. 排查类加载机制:检查Tecnico类的类加载情况,确保运行时类加载器能正确加载该类。比如核对Spring组件扫描路径,或模块化项目中是否正确导出该类所在模块。
  4. 校验方法参数类型:确认findWithUser()返回集合的元素类型与toDTO方法参数类型匹配,检查导入语句确保Tecnico是正确的目标类。

内容的提问来源于stack exchange,提问作者Alejandro Palacios Sanz

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 13:35:04