繁体   English   中英

通用类型擦除警告

[英]Generic Type Erasure Warning

我从Thinking in Java一书中得到了这个代码,Bruce在调用方法set()时指出了警告。 代码如下:

    package testPackage;

    class GenericBase<T> {
    private T element;
    public void set(T arg) { arg = element; }
    public T get() { return element; }
    }
    class Derived1<T> extends GenericBase<T> {}
    class Derived2 extends GenericBase {} // No warning
    // class Derived3 extends GenericBase<?> {}
    // Strange error:
    // unexpected type found : ?
    // required: class or interface without bounds
    public class ErasureAndInheritance {
    @SuppressWarnings("unchecked")
    public static void main(String[] args) {
        Derived2 d2 = new Derived2();
        Object obj = d2.get();
        d2.set(obj); // Warning here!
        }
    }

如果我删除注释,我会收到以下警告:
类型安全:方法集(Object)属于原始类型GenericBase。 应参数化对泛型类型GenericBase的引用

我的问题是,为什么警告显示在set()方法上? 有人可以解释一下这个警告意味着什么吗?
顺便说一句,我是Java Generics的新手,虽然我读了关于泛型的其他问题,但我仍然对Erasure感到困惑。

来自Java doc 这里

泛型被引入到Java语言中,以便在编译时提供更严格的类型检查并支持泛型编程。 为了实现泛型,Java编译器将类型擦除应用于:

  • 如果类型参数是无界的,则将泛型类型中的所有类型参数替换为其边界或对象。 因此,生成的字节码仅包含普通的类,接口和方法。
  • 如有必要,插入类型铸件以保持类型安全。
  • 生成桥接方法以保留扩展泛型类型中的多态性。
  • 类型擦除确保不为参数化类型创建新类; 因此,泛型不会产生运行时开销。

简单:在编译过程之后,每个泛型都是一个Object ,它只是为您添加了转换,如果您做错了,它将生成编译器错误。

关于unchecked注释,当编译器无法确定您正在做什么是正确的时使用它(事实上,您使用的原始类型与GenericBase<Object>

除了类型T之外,你有自set方法以来的警告但由于你使用的是原始类型,它不知道T是什么,并生成此警告以告知您正在使用原始类型(坏事)。

您可以使用注释来说:“我知道它是原始类型,但我知道它是合法的,我知道我在做什么”。

混合原始类型和泛型类型是可能的,因为泛型的实现方式,如上所述,在编译器处理之后, T变为Object ,这意味着像GenericBase这样的原始对象与GenericBase<T>

它没有要求使用泛型的任何转换的原因是因为它将为您添加转换(并且您可以确保代码将始终在运行时工作而不用担心可能的ClassCastException )。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM