通用接口和通配符

时间:2016-06-16 10:13:26

标签: java generics wildcard

所以,我这里有一个小班级层次结构:

public class Tst2 {
    /** interface allowing copying */
    private interface Copyable<T> {
        void copyFrom(T original);
    }

    /** Class which can be parameterized by types which can self-copy so it can copy those objects when it needs */
    private static class Manager<T extends Copyable<T>> {
        T value;

        Manager(final T value) {
            this.value = value;
        }

        void someWork() {
            value.copyFrom(value);
        }
    }

    /** and here's one example of the self-copying class for Manager to manipulate */
    private static class Box<T> implements Copyable<Box<T>> {
        T value;

        Box(final T value) {
            this.value = value;
        }

        T getValue() {
            return value;
        }

        void setValue(final T value) {
            this.value = value;
        }

        public void copyFrom(Box<T> original) {
            this.setValue(original.getValue());
        }
    }

    public static void main(String[] args) {
        Box<Object> objBox = new Box<Object>("object value");
        Manager<Box<Object>> objectManager = new Manager<>(objBox); // we have manager of Boxes with Objects
        objectManager.someWork();

        Box<String> strBox = new Box<String>("string value");
        Manager<Box<String>> stringManager = new Manager<>(strBox); // and here's manager of Boxes with Strings
        stringManager.someWork();   // all works well
    }
}

这一切都很美妙。是的,你可以用不同的方式写它,但我喜欢这种特殊的方式 - 它简洁,并提供我想要的一切。

所以我可以创建Manager<Box<String>>和其他所有具体实现,完美。 现在让我们尝试通过声明变量来创建任何Box的管理器:

Manager<Box<?>> anyManager;

想要做一些类似以下的事情:

anyManager = (Manager<Box<?>>) (Manager<?>) new Manager<Box<Object>>(objBox);

Ooops,DECLARING变量的问题(我还没有做任何演员):

Error:(52, 20) java: type argument Tst2.Box<?> is not within bounds of type-variable T

因此,您无法创建任何Manager<Box<?>>!但是肯定ANY Box实现了Copyable,所以它应该适合那个

class Manager<T extends Copyable<T>>

右? 我想它并没有考虑到我的所有Box都实现了相同类型的Box的可复制的事实,所以它认为那个通配符可以来自不同的盒子,或类似的东西?

有人可以解释一下和/或建议解决方法吗? 再一次 - 我对重写整个解决方案的人不感兴趣,我只对修复这个特定的位感兴趣。或者,至少,解释发生了什么。

1 个答案:

答案 0 :(得分:1)

这是javac或ecj中的错误,在这些情况下通常ecj是正确的。

但有人可能会说:

能够复制&LT;盒及LT;?&GT;&GT;不是Box&lt;?&gt;的超类型? (甚至ecj会告诉你)。但那就是当你用Box&lt;?&gt;替换T时,Manager上所需的类型是什么。