不兼容的java泛型类

mr.*_*ing 8 java generics types

似乎我再次陷入java泛型.这是我有的:

几堂课:

class CoolIndex implements EntityIndex<CoolEntity>

class CoolEntity extends BaseEntity

枚举使用上面的类:

enum Entities {
    COOL_ENTITY {
        @Override
        public <E extends BaseEntity, I extends EntityIndex<E>> Class<I> getIndexCls() {
            return CoolIndex.class;
        }

        @Override
        public <E extends BaseEntity> Class<E> getEntityCls() {
            return CoolEntity.class;
        }
    }

    public abstract <E extends BaseEntity, I extends EntityIndex<E>> Class<I> getIndexCls();

    public abstract <E extends BaseEntity> Class<E> getEntityCls();    
}
Run Code Online (Sandbox Code Playgroud)

函数我需要使用getIndexCls()函数调用的结果调用:

static <E extends BaseEntity, I extends EntityIndex<E>> boolean isSomeIndexViewable(Class<I> cls)
Run Code Online (Sandbox Code Playgroud)

问题是编译器抱怨return CoolIndex.class;并且return CoolEntity.class;我不清楚为什么......当然我可以把它投入Class<I>(第一种情况)但在我看来我似乎试图掩盖我的误解并且感觉不对.

rge*_*man 3

问题在于getIndexCls,因为它是通用的,所以类型参数可以解释为符合声明范围的任何类。您可能认为这CoolIndex.class符合这些界限,而且确实如此,但是该方法的调用者可以提供自己的类型参数,这将是不兼容的,例如:

Entities.COOL_ENTITY.<UncoolEntity, UncoolIndex>getIndexCls();
Run Code Online (Sandbox Code Playgroud)

这会破坏类型安全,因此编译器不允许这样做。您可以强制转换为Class<I>,但出于同样的原因,编译器会警告您未经检查的强制转换。它会编译,但可能会导致运行时问题,正如我所描述的。

其他情况可以通过传递一个对象以使类型推断正常工作来解决这种情况Class<I>,但这违背了此方法的要点——返回一个Class<I>对象。

其他情况要求将泛型类型参数从方法移动到类,但您使用的是枚举,它不能是泛型的。

我想出的获得类似于编译的东西的唯一方法是完全删除enum。使用抽象类,以便您可以声明类级别的类型参数。使用您想要的类型参数实例化常量。

abstract class Entities<E extends BaseEntity, I extends EntityIndex<E>> {
    public static final Entities<CoolEntity, CoolIndex> COOL_ENTITY = new Entities<CoolEntity, CoolIndex>() {
        @Override
        public Class<CoolIndex> getIndexCls() {
            return  CoolIndex.class;
        }

        @Override
        public Class<CoolEntity> getEntityCls() {
            return CoolEntity.class;
        }
    };

    // Don't instantiate outside this class!
    private Entities() {}

    public abstract Class<I> getIndexCls();
    public abstract Class<E> getEntityCls();
}
Run Code Online (Sandbox Code Playgroud)