我有两种方法:
public <T extends Component> void addComponent(BluePrint bluePrint, Class<T> type) throws InstantiationException, IllegalAccessException {
AddComponent addComponent = addComponentMap.get(type);
if (addComponent == null) {
addScriptable(bluePrint, type); <--- fails here
}
}
if addComponentMap.get(type);
返回 null,我隐含地知道 T 是 Scriptabe 类型并且需要调用:
private <T extends Scriptable> void addScriptable(BluePrint bluePrint, Class<T> type) throws InstantiationException, IllegalAccessException {
scriptableSystems.add(new ScriptableSystem<T>());
}
问题在于,第二个方法中 T 的上限是可编写脚本的,而第一个方法中 T 的上限是 Component,因此当 addComponent 为 null 时,类型“可能”可能是任何组件。
当 addComponent 为 null 时,我可以以某种方式将约束缩小到 Scritpable 吗?或者以某种方式明确地说,当 addComponent 为 null 时,T 将在调用 addScriptable 之前扩展 Scriptable?
也许值得一提的是,Scriptable 继承自组件。
最佳答案
The issue is that the upper bound for T in the second method is Scriptable and in the first method its Component, therefore type "could" potentially be any component when addComponent is null.
这是正确的,但我想说得更强烈:因为 Scriptable
扩展 Component
(而不是相反),类型参数 T方法
可以始终是不受 Scriptable 限制的类型。addComponent()
中的
当然。假设您在其他情况下不希望有更严格的限制,这就是强制转换的用途:Can i somehow narrow the constraint to Scritpable when addComponent is null?
public <T extends Component> void addComponent(BluePrint bluePrint, Class<T> type)
throws InstantiationException, IllegalAccessException {
AddComponent addComponent = addComponentMap.get(type);
if (addComponent == null) {
addScriptable(bluePrint, (Class<? extends Scriptable>) type);
}
}
您当然会收到有关强制转换的编译器警告。这是正确且正确的,因为该代码取决于编译器无法验证的条件。
Or somehow explicitly say that when addComponent is null T will extend Scriptable, before calling addScriptable?
这正是您通过强制转换所做的所说的。引用类型值的强制转换实际上是一个断言,表明您对该值的运行时类型的了解比编译器可以证明的更多。
此外,如果您希望有与 ClassCastException
不同的 filaure 行为,则可以执行运行时测试:
if (!Scriptable.class.isAssignableFrom(type)) {
throw new MyChosenException();
}
关于Java泛型问题,修改约束?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46773076/