我使用 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>
,但是这个Map
与 Map<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/