我还面临着另一个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<?”这将解决这个问题。然而,我想知道是否有一些更干净的东西可以做,并可以在运行时保存在回调方法中的造型。
1条答案
按热度按时间t2a7ltrp1#
您可以简单地在BaseService Service中提供onPostUpdate,如下所示:
此外,您正在对通配符serviceBean调用onPostUpdate方法,而不是具体类型。因此,当构造函数采用BaseService类的具体类型时,编译器会为它大声呼喊。