首页 > 解决方案 > 使用泛型类型参数存储对类的引用及其实现

问题描述

我正在使用 aMap来存储对泛型类型参数类和具有相同泛型类型参数的实现对象的引用,更具体地说:

public class SomeImpl<T extends BaseClass> {

    void execute(T instance);
}

现在,在另一个类中,我想根据它们的泛型类型参数存储对实现的引用。

private Map<Class<BaseClass>, SomeImpl<BaseClass>> map;

但是,我发现在这里使用泛型操作有点令人困惑,特别是因为显示了许多不安全的强制转换警告。

private <T extends BaseClass> void register(SomeImpl<T> impl, Class<T> aClass) {
    // unsafe
    Class<BaseClass> configClass = (Class<BaseClass>) aClass; 
    // unsafe
    map.put((SomeImpl<BaseClass>) impl, configClass);
}

后来当我想检索一些实例时

private SomeImpl<BaseClass> get(Class<? extends BaseClass> aClass) {
    // unsafe
    return (SomeImpl<BaseClass>) map.get(aClass); 
}

有人可以澄清上述陈述是否安全,因此可以安全地忽略警告吗?

标签: javagenerics

解决方案


最后,我确实采用了以下解决方案。非常感谢 Radiodef,他向我指出了使用类型安全的异构容器。

private Map<Class<?>, SomeImpl<?>> map = new HashMap<>();

以下方法将添加/获取具体实现:

public <T extends BaseClass> void addImpl(SomeImpl<T> loader, Class<T> aClass) {
    map.put(type, loader);
}

public <T extends BaseClass> SomeImpl<T> getImpl(Class<T> aClass) {
    return (SomeImpl<T>) map.get(type);
}

最初,我也在寻找一种可以使用 any 调用的方法BaseClass。我发现这种模式不可能做到这一点,所以下面的伎俩:

public SomeImpl<BaseClass> getBaseImpl(Class<? extends BaseClass> aClass) {
    return (BaseLoader<BaseClass>) map.get(type);
}

这确实是一个真正不保存的强制转换,因为编译器无法确保BaseClass传递了正确的类型。但是,我可以确保始终传递正确的类型(或强制使用isAssignableFrom)。

这允许我BaseClass从数据库加载一些对象,例如:

List<BaseClass> list = getSomeBaseClasses();

Map<Class<? extends BaseClass>, List<BaseClass> map = list.stream()
    .collect(Collectors.groupingBy(BaseClass::getClass));

map.forEach((aClass, bases) -> {
    SomeImpl<BaseClass> impl = getBaseImpl(aClass);
    impls.forEach(impl::execute);
}

推荐阅读