[英]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.