Java泛型问题,修改约束?

时间:2017-10-16 14:47:11

标签: java generics

我有两种方法:

   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的上限是Scriptable,而在第一种方法中它是Component,因此键入&#34;可以&#34;当addComponent为null时,可能是任何组件。

当addComponent为null时,我可以以某种方式将约束缩小到Scritpable吗?或者以某种方式明确地说当addComponent为null时,T会在调用addScriptable之前扩展Scriptable吗?

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

2 个答案:

答案 0 :(得分:1)

  

问题是第二种方法中T的上限是   脚本和第一种方法中的Component,因此键入   当addComponent为null时,“可能”可能是任何组件。

这是正确的,但我更强烈地说:因为Scriptable扩展Component(而不是相反),在方法{{1}中输入参数T 总是是一个不受Scriptable限制的类型。

  

当addComponent为时,我可以以某种方式将约束缩小到Scritpable   空?

不确定。假设你不想在其他情况下更严格的约束,那就是施法:

addComponent()

您当然会收到关于演员表的编译器警告。这是正确的,因为该代码取决于编译器无法验证的条件。

  

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

这正是你通过施法所说的。具有引用类型值的强制转换实际上是一个断言,您可以更多地了解该值的运行时类型,而不是编译器可以证明的。

此外,如果您的灯丝行为与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); } } 不同,则可以执行运行时测试:

ClassCastException

答案 1 :(得分:0)

如果您无法缩小地图中类的泛型类型,您仍然可以进行投射。为了更安全,您可以使用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) { }

这甚至不需要空检查,并且可以适用于addComponent不为空的情况。在您的示例中,您将执行以下操作:

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