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

同Class对象抛出java.lang.ClassCastException的原因及解决方法

问题描述

在对同一类的对象进行类型转换时遇到java.lang.ClassCastException错误,触发错误的代码如下:

try (Session session = configDatabaseService.getSessionFactory().openSession())
{
    List list = session.createQuery("FROM SparelabsPollStatusDetailEntity detail WHERE detail.dateAdded>:dateAdded")
            .setParameter("dateAdded", Instant.ofEpochMilli(new Date(System.currentTimeMillis() - (2 * 24 * 3600 * 1000L)).getTime()))
            .list();

    for (Object spareLabsPollStatusDetail : list)
    {
        Optional<DimResident> dimResident = this.dimResidentRepository.findById(
                Math.toIntExact(((SparelabsPollStatusDetailEntity) (spareLabsPollStatusDetail)).getDimResidentId())
        );

        if (dimResident.isPresent())
        {
             // 省略业务代码
        }
        else
        {
            System.out.println("NOT Updated dimResident SpareLabsKey  = [" + dimResident.get().getResidentID() + "]");
        }
    }
}
catch (Exception e)
{
    System.err.print(e);
    if (Logger.isErrorEnabled())
        Logger.error(e);
}

对应的错误信息:

java.lang.ClassCastException: class com.rossmoor.sparelabs.model.entities.SparelabsPollStatusDetailEntity cannot be cast to class com.rossmoor.sparelabs.model.entities.SparelabsPollStatusDetailEntity (com.rossmoor.sparelabs.model.entities.SparelabsPollStatusDetailEntity is in unnamed module of loader 'app'; com.rossmoor.sparelabs.model.entities.SparelabsPollStatusDetailEntity is in unnamed module of loader org.springframework.boot.devtools.restart.classloader.RestartClassLoader @86fbeb3)
2022-09-25 18:31:56,588 WARN  [HikariPool-1 housekeeper] com.zaxxer.hikari.pool.HikariPool$HouseKeeper: HikariPool-1 - Thread starvation or clock leap detected (housekeeper delta=55s727ms524µs300ns).
    2022-09-25 18:31:57:310 [ERROR] [restartedMain:ID=22]:[SpareLabsClientServiceImpl.java:834] java.lang.ClassCastException: class com.rossmoor.sparelabs.model.entities.SparelabsPollStatusDetailEntity cannot be cast to class com.rossmoor.sparelabs.model.entities.SparelabsPollStatusDetailEntity (com.rossmoor.sparelabs.model.entities.SparelabsPollStatusDetailEntity is in unnamed module of loader 'app'; com.rossmoor.sparelabs.model.entities.SparelabsPollStatusDetailEntity is in unnamed module of loader org.springframework.boot.devtools.restart.classloader.RestartClassLoader @86fbeb3)
        at com.rossmoor.sparelabs.services.web.SpareLabsClientServiceImpl.updateSpareLabsKeysInDimResidentTable(SpareLabsClientServiceImpl.java:794)
        at com.rossmoor.sparelabs.services.web.SpareLabsClientServiceImpl.doDataSynchronization(SpareLabsClientServiceImpl.java:574)
        at com.rossmoor.sparelabs.SpareLabsApplication.run(SpareLabsApplication.java:147)
        at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:771)
        at org.springframework.boot.SpringApplication.callRunners(SpringApplication.java:755)
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:315)
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:1306)
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:1295)
        at com.rossmoor.sparelabs.SpareLabsApplication.main(SpareLabsApplication.java:47)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.base/java.lang.reflect.Method.invoke(Method.java:568)
        at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:49)

错误含义

这个看似矛盾的异常,本质原因是类加载器不一致:

  • 一个SparelabsPollStatusDetailEntity类由系统类加载器(loader 'app')加载
  • 另一个同名类由Spring Boot DevTools的RestartClassLoader加载

Java中判断两个类是否为同一类型,不仅要看全类名,还要看加载它们的类加载器是否相同。即使字节码完全一致,不同类加载器加载的类也会被视为不同类型,因此无法互相转换。

解决方案

方案1:禁用Spring Boot DevTools(快速解决)

如果不需要热重启功能,直接移除项目依赖中的DevTools:

  • Maven:删除pom.xml中这段配置
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-devtools</artifactId>
    <scope>runtime</scope>
    <optional>true</optional>
</dependency>

删除后重新构建项目即可。

方案2:配置DevTools,指定类加载规则(保留热重启)

如果需要保留热重启功能,可通过配置让实体类由系统类加载器加载,避免重复加载:
在src/main/resources/application.properties中添加:

# 指定实体类包不参与DevTools的重启类加载
spring.devtools.restart.exclude=com/rossmoor/sparelabs/model/entities/**

方案3:优化代码,使用泛型查询(辅助优化)

原代码使用未指定泛型的List,强制类型转换容易引发问题。改为泛型查询可在编译期发现类型问题,避免不必要的强制转换:

// 使用泛型Query直接获取指定类型的List
List<SparelabsPollStatusDetailEntity> list = session.createQuery(
        "FROM SparelabsPollStatusDetailEntity detail WHERE detail.dateAdded>:dateAdded",
        SparelabsPollStatusDetailEntity.class
).setParameter("dateAdded", Instant.ofEpochMilli(new Date(System.currentTimeMillis() - (2 * 24 * 3600 * 1000L)).getTime()))
 .list();

// 循环时无需强制转换
for (SparelabsPollStatusDetailEntity spareLabsPollStatusDetail : list) {
    Optional<DimResident> dimResident = this.dimResidentRepository.findById(
            Math.toIntExact(spareLabsPollStatusDetail.getDimResidentId())
    );
    // 后续逻辑不变
}

内容的提问来源于stack exchange,提问作者Ram

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 19:50:43