Java中的泛型无法编译

我被困在试图了解这里到底发生了什么。使用 copy_v1 方法的两种方式如下所示。第一种方式 (1) 会产生编译错误。但是第二种方式 (2) 不会产生任何编译错误(当我注释掉 (1) 后尝试执行程序时,它也不会产生任何运行时错误)。当我用 替换 (2) 时copy_v1(new Wrapper<String>("Hello"), new Wrapper<Object>(new Object()));,我最终也会在 (2) 上遇到编译错误。不知道发生了什么。(1) 上的代码与 (2) 上的代码有何不同?有人可以对此有所了解吗?

谢谢。

public class SOQuestion {

    public static <T> void copy_v1(Wrapper<T> source, Wrapper<T> dest) {
        T srcObj = source.getRef();
        dest.setRef(srcObj);
    }

    public static void main(String[] args) {
        Wrapper<Object> objectWrapper = new Wrapper<>(new Object());
        Wrapper<String> stringWrapper = new Wrapper<>("Hello");
        copy_v1(stringWrapper, objectWrapper); // Compile error on this line (1)
        copy_v1(new Wrapper<>("Hello"), new Wrapper<>(new Object())); // But no error on this line (2)
    }

}

class Wrapper<T> {

    private T ref;

    Wrapper(T ref) {this.ref = ref;}

    public T getRef() {return this.ref;}

    public void setRef(T ref) {this.ref = ref;}
}

回答

在 中copy_v1(stringWrapper, objectWrapper);,无法推断Tfor的泛型参数copy_v1。实际上没有有效的类型T,因此调用是有效的。

如果TString,则第二个参数不能转换为Wrapper<String>Wrapper<Object>不是一种Wrapper<String>,因为你可以调用setRef(new Object())前者,但不能调用后者。我知道您没有在 中这样做copy_v1,但是编译器不会查看方法中发生的情况来确定调用是否有效。

同样,如果TObject,则第一个参数不能转换为Wrapper<Object>Wrapper<String>不是一种Wrapper<Object>String当您调用getRef前者时,您肯定会得到一个,但不会调用后者。

但是,在 中copy_v1(new Wrapper<>("Hello"), new Wrapper<>(new Object()));,您也要求编译器推断Wrappers的类型参数。在这种情况下,编译器会尽力使您的方法调用有效,并像这样推断:

SOQuestion.<Object>copy_v1(new Wrapper<Object>("Hello"), new Wrapper<Object>(new Object()));

Tforcopy_v1Object,并且Ts 的Wrappers 都是Object。现在一切都是有效的。new Wrapper<Object>接受一个Object参数,并且"Hello"可以传递给它,因为String继承自Object.

请注意,如果您将您的更改copy_v1为:

public static <T> void copy_v1(Wrapper<? extends T> source, Wrapper<? super T> dest) {
    T srcObj = source.getRef();
    dest.setRef(srcObj);
}

然后做copy_v1(stringWrapper, objectWrapper);就好了。这限制了您可以使用destsource在方法内部执行的操作,但允许调用者将例如传递Wrapper<String>dest应该使用Wrapper<Object>.


以上是Java中的泛型无法编译的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>