在Room Dao中是否支持向上转型?附代码示例说明问题
Room Dao是否支持向上转型?
简单来说:Room Dao 本身不直接支持返回父类型(比如你的User接口)的查询结果,但可以通过简单的额外处理实现类似效果。
为什么你的当前代码没问题,但直接向上转型不行?
你现在的UserImplDao返回List<UserImpl>是完全正常的——因为UserImpl是标注了@Entity的实体类,Room能明确它和数据库表的映射关系,知道如何把数据库行转换成UserImpl对象。
但如果把返回类型改成List<User>(也就是向上转型到父接口),Room会直接报错。原因很简单:Room的查询结果映射依赖于返回类型的字段定义,而User只是一个接口,没有任何数据库列对应的字段,Room根本不知道怎么把数据库里的UserImpl数据映射到User实例上。
实现类似向上转型效果的两种方法
1. 手动转换(最直接的方案)
先查询出实体类列表,再通过代码把它们转型为父类型。如果用Java 8+,还可以在Dao里写默认方法来封装这个逻辑:
@Dao public interface UserImplDao { @Query("SELECT * FROM UserImpl") List<UserImpl> getAllUserImpls(); // 封装转型逻辑,对外暴露父类型列表 default List<User> getAllUsers() { return getAllUserImpls().stream() .map(userImpl -> (User) userImpl) .collect(Collectors.toList()); } }
这样外部调用getAllUsers()就能拿到List<User>,完全满足向上转型的需求。
2. 借助中间POJO(适合复杂场景)
如果你的父类型是抽象类而非接口,且包含实体类的核心字段,可以创建一个包含@Embedded注解的POJO来间接实现,但对于接口来说这个方案意义不大——毕竟接口本身没有字段,最终还是要依赖实体类的实例来转型。
总结
Room不支持直接返回非实体的父类型,但通过先查询实体再手动转型的方式,完全可以实现你想要的向上转型效果,而且这种方式也符合Room的设计逻辑(始终基于实体类做数据库映射)。
内容的提问来源于stack exchange,提问作者AW13




