Java泛型不兼容类型转换

332nm8kg  于 2023-05-15  发布在  Java
关注(0)|答案(1)|浏览(150)

我还面临着另一个Java泛型问题,需要帮助。
我有一个实体类,它应该能够携带自己类型的对象:

public abstract class BaseEntity<E extends BaseEntity<E>> {

    private E obj;

    [...]
}

还有一个Service类,它将在实体之上提供业务逻辑,我需要一个回调:

public abstract class BaseService<E extends BaseEntity<E>> {

    public void onPostUpdate(E entity) {

    }

    [...]
}

现在,Hibernate侦听器类必须能够调用服务类回调:

@RequiredArgsConstructor
public class EntityListenerImpl implements PostUpdateEventListener {

    private final ApplicationContext applicationContext;

    @PostConstruct
    private void init() {
        [...]
    }

    @Override
    public void onPostUpdate(PostUpdateEvent event) {
        BaseEntity<?> entity = (BaseEntity<?>) event.getEntity();
        final Class<?> serviceClass;
        try {
            serviceClass = Class.forName(entity.getClass().getName() + "Service");
        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
        }
        if( serviceClass.isAssignableFrom(BaseService.class) ) {
            BaseService<?> serviceBean = (BaseService<?>) applicationContext.getBean(serviceClass);
            serviceBean.onPostUpdate( entity );
        }
    }

    [...]
}

侦听器正在寻找正确的服务bean,并执行附加了实体的回调方法。整个代码不在这里(空检查已经被剥离等等)。为了提高效率,实体类和服务类之间的Map应该在init时一次性完成并存储在Map中。但这不是重点。
在编译时,我找不到避免这种错误的方法:

EntityListenerImpl.java:26: error: incompatible types: BaseEntity<CAP#1> cannot be converted to CAP#2
            serviceBean.onPostUpdate( entity );
                                      ^
  where CAP#1,CAP#2 are fresh type-variables:
    CAP#1 extends BaseEntity<CAP#1> from capture of ?
    CAP#2 extends BaseEntity<CAP#2> from capture of ?

我可以更改回调签名,使其接受Object而不是BaseEntity<?”这将解决这个问题。然而,我想知道是否有一些更干净的东西可以做,并可以在运行时保存在回调方法中的造型。

t2a7ltrp

t2a7ltrp1#

您可以简单地在BaseService Service中提供onPostUpdate,如下所示:

public void onPostUpdate(BaseEntity<?> entity) {
       
}

此外,您正在对通配符serviceBean调用onPostUpdate方法,而不是具体类型。因此,当构造函数采用BaseService类的具体类型时,编译器会为它大声呼喊。

相关问题