Java泛型问题,修改约束



我有两种方法:

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
}
}

如果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的上界是可脚本化的,而在第一个方法中它是Component,因此当addComponent为null时,类型"可能"可能是任何组件。

当addComponent为null时,我能以某种方式将约束缩小到Scriteable吗?或者以某种方式明确表示,当addComponent为null时,T将在调用addScriptable之前扩展Scriptable?

也许值得一提的是,Scriptable继承自组件。

问题是第二种方法中T的上界是Scriptable,并且在第一个方法中是它的Component,因此键入当addComponent为null时,"可能"可能是任何组件。

这差不多是对的,但我更强烈地说:由于Scriptable扩展了Component(而不是相反),方法addComponent()中的类型参数T可以始终是不受Scriptable约束的类型。

当addComponent为无效的

当然。假设你不想在其他情况下有更严格的界限,这就是铸造的目的:

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);
}
}

您当然会收到一个关于强制转换的编译器警告。这是正确的,因为代码依赖于编译器无法验证的条件。

或者以某种方式明确表示,当addComponent为null时,T将在调用addScriptable之前扩展Scriptable?

这正是你通过选角所做的所说的。引用类型的值的强制转换实际上是一种断言,即您对该值的运行时类型的了解比编译器所能证明的要多。

此外,如果您希望具有不同于ClassCastException:的过滤行为,则可以执行运行时测试

if (!Scriptable.class.isAssignableFrom(type)) {
throw new MyChosenException();
}

如果不能缩小映射中类的泛型类型,则仍然可以强制转换。为了更安全,您可以使用Class.isAssigneableFrom,它是类(而不是对象)的实例:

public static void main(String[] args) {
Map<String, Class<? extends Number>> map = new HashMap<>();
Class<? extends Number> someNumberClass = map.get("Double");
if (Integer.class.isAssignableFrom(someNumberClass)) {
acceptInteger((Class<Integer>) someNumberClass);
}
}
public static void acceptInteger(Class<Integer> c) { }

这甚至不需要null检查,并且可以适用于addComponent不为null的情况。在你的例子中,你会做:

if (Scriptable.class.isAssignableFrom(type)) { // add the null check if necessary
addScriptable(bluePrint, (Class<Scriptable>) type);
}

最新更新