用抽象类方法解决Java泛型类型错误

Vis*_*kia 11 java generics abstract-class generic-type-argument

我想在java中实现类似的东西,但是得到编译时错误:

AbstractTestLoader类型中的onMessage(TextMessage,Class)方法不适用于参数(TextMessage,Class)

我理解这个错误的原因,但我也觉得应该有一些方法来实现这一点,或者可能是其他方式.

public abstract class AbstractTestLoader<T extends AbstractEntity<T>> {

    public void onMessage(TextMessage message) throws Exception {
        onMessage(message, this.getClass()); // I want to correct this line in such a way so that I can call below method with actual Class of {T extends AbstractEntity<T>}
    }

    public void onMessage(TextMessage message, Class<T> clazz) throws Exception {
        //here my original logic will go
    }
}
Run Code Online (Sandbox Code Playgroud)

gle*_*e8e 5

应该注意的是,虽然Java泛型在运行时被擦除,但如果它们存在于类文件中,则检索它们的反射apis有限.

以下是这些假设的快速解决方案:

  1. AbstractTestLoader 是超级直接的.
  2. 声明超类时,子类不使用类型通配符,例如class GenericLoader<T extends SubclassAbstractEntity<T>> extends AbstractTestLoader<T>,不存在这样的子类.

这是代码:

public class AbstractTestLoader<T extends AbstractEntity<T>> {

    private static final ClassValue<Class<?>> TYPE_PARAMETER_CACHE = new ClassValue<Class<?>>() {
        @Override
        protected Class<?> computeValue(Class<?> type) {
            assert AbstractTestLoader.class.isAssignableFrom(type);
            assert type.getSuperclass() == AbstractTestLoader.class;
            Type genericSuperclass = type.getGenericSuperclass();
            assert genericSuperclass instanceof  ParameterizedType;
            Type entityType = ((ParameterizedType) genericSuperclass).getActualTypeArguments()[0];
            assert entityType instanceof  Class<?>;
            return (Class<?>) entityType;
        }
    };

    @SuppressWarnings("unchecked")
    protected Class<T> getEntityType() {
        return (Class<T>) TYPE_PARAMETER_CACHE.get(this.getClass());
    }

    public void onMessage(Object message) throws Exception {
        onMessage(message, getEntityType()); // getting compile time error here
    }

    public void onMessage(Object message, Class<T> clazz) throws Exception {
        //here my original logic will go
    }
}
Run Code Online (Sandbox Code Playgroud)

getEntityType可以在子类在那两个假设不能被重写.


Vis*_*kia 4

最后,经过几次尝试,我得到了简单且可行的解决方案,但如果可能的话,我仍然愿意听到其他最佳答案。谢谢

public abstract class AbstractTestLoader<T extends AbstractEntity<T>> {

    abstract Class<T> getEntityType();

    public void onMessage(TextMessage message) throws Exception {
        onMessage(message, getEntityType());
    }

    public void onMessage(TextMessage message, Class<T> clazz) throws Exception {
        //here my original logic will go
    }
}
Run Code Online (Sandbox Code Playgroud)