java - 如何减少泛型<?将 Type> 扩展为 Java 中的 Type。代码在运行时有效但无法编译

标签 java generics

我使用 Spring Boot .yaml 进行配置并创建配置类的层次结构,以便其他应用程序可以定义其他属性。 Config本身具有层次结构。

为了保持其开放以供扩展,我使用 <? extends Type>通用声明。

当我尝试减少 <? extends Type> 时,这会导致问题至Type .

以下完全有效的最小示例演示了问题(在 getSubConfs 方法中):

public static class Conf<S> {
    public String name;
    public Map<String, S> subConfs;
}

public static class SubConf {
    public String name;
    public Conf<? extends SubConf> conf;
}

public static Map<String, SubConf> getSubConfs(SubConf subconf) {
    // incompatible types: java.util.Map<java.lang.String,capture#1 of ? extends App.SubConf>
    // cannot be converted to java.util.Map<java.lang.String,App.SubConf>
    return subconf.conf.subConfs;
}

public static void main(String[] args) {
    Conf<SubConf> cfg = new Conf<>();
    cfg.name = "cfg";
    SubConf subcfg = new SubConf();
    subcfg.name = "subcfg";
    subcfg.conf = cfg;
    cfg.subConfs = new HashMap<>();
    cfg.subConfs.put(subcfg.name, subcfg);

    Map<String, SubConf> subConfs = getSubConfs(subcfg);
    System.out.println(subConfs.get("subcfg").name);
}

关于 getSubConfs(subcfg)调用我期望获得 Map<String, SubConf>因为我不关心 subcfg 进一步可能的特化,我只需要访问公共(public)属性。

有效代码是:

public static Map<String, ? extends SubConf> getSubConfs2(SubConf subconf) {
    Conf<? extends SubConf> cfg = subconf.conf;
    return cfg.subConfs;
}

但我不明白为什么我应该有 ? extends SubConf如果在运行时没有类型问题,则在 API 中。

更新功能:

public static Map<String, SubConf> getSubConfs(SubConf subconf) {
    Conf<? extends SubConf> cfg = subconf.conf;
    return (Map<String, SubConf>) cfg.subConfs;
}

显示代码不存在任何运行时问题,即使使用-XLint:unchecked :

warning: [unchecked] unchecked cast
    return (Map<String, SubConf>) cfg.subConfs;
required: Map<String,SubConf>
found:    Map<String,CAP#1>
where CAP#1 is a fresh type-variable:
  CAP#1 extends SubConf from capture of ? extends SubConf

当然我可以用@SuppressWarnings("unchecked")来装饰函数.

最佳答案

你的方法有问题getSubConfs()SubConf.conf类型为Conf<? extends SubConf> 。然后Conf.subConfs类型为Map<String, ? extends SubConf> ,但是这个MapMap<String, SubConf> 不兼容你想要得到。

不兼容的原因是无法判断 Map<String, ? extends SubConf> 中 SubConf 的实现是什么。您可以从中读取 SubConf 值,但不能向其中添加任何内容(最终可能会混合不同的实现)。 Map<String, SubConf>清楚其类型,您可以安全地读取并向其中添加项目:

// Assuming SubConf2 and SubConf3 both extend SubConf ...
HashMap<String, SubConf2> map = new HashMap<>();
Map<String, ? extends SubConf> subconfMap = map;
// This doesn't work, because then you could call map.get("key") 
// and get SubConf3 which is not compatible with the declared SubConf2
subconfMap.put("key", new SubConf3());

// The problem cannot happen with with Map<String, SubConf>, because
// the following statement causes compile time error:
Map<String, SubConf> subconfMap = new HashMap<String, SubConf2>();

关于java - 如何减少泛型<?将 Type> 扩展为 Java 中的 Type。代码在运行时有效但无法编译,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43627743/

相关文章:

java - 为什么这个带有有界通配符的 Java 通用代码无法编译?

java - 为什么 PropertyDescriptor 和 Reflection 在 1.7 中与在 1.6 中对于泛型的工作效果不同?

Java泛型方法使用compareTo方法问题从集合中查找 'max'对象

java - 无法在不指定类型参数的情况下将 Java 8 方法与 lambda 参数一起使用

java - 一个 Java applet 中的两个线程最佳实践

java - EJB3 Query + in 子句

java - 如何让我的按钮单击显示与我的随机 TextView 相对应的 ImageView?

Java - 如何在 File[] 中收集结果后填充字符串数组

java - 安卓工作室 : Change EditText filed from a java class

c# - 有没有办法将字符串转换为类型?