北京北大青鸟学校学术部讲解:与非泛型代码相互操作
北京北大青鸟学校学术部专家表示:数百万行现有代码使用已经泛型化的Java类库中的类,比如集合框架、Class 和 ThreadLocal。JDK 5.0 中的改进不要破坏所有这些代码是很重要的,所以编译器允许在不指定其类型参数的情况下使用泛型类。(北大青鸟课程)
当然,北京北大青鸟学校老师表示,以“旧方式”做事没有新方式安全,因为忽略了编译器准备提供的类型安全。如果试图将 List<String> 传递给一个接受 List 的方法,它将能够工作,但是编译器将会发出一个可能丧失类型安全的警告,即所谓的“unchecked conversion(不检查转换)”警告。(北大青鸟课程)
没有类型参数的泛型,比如声明为 List 类型而不是 List<Something> 类型的变量,叫做原始类型。原始类型与参数化类型的任何实例化是赋值兼容的,但是这样的赋值会生成 unchecked-conversion 警告。(北大青鸟课程)
为了消除一些 unchecked-conversion 警告,假设您不准备泛型化所有的代码,您可以使用通配符类型参数。使用 List<?> 而不使用 List。List 是原始类型;List<?> 是具有未知类型参数的泛型。编译器将以不同的方式对待它们,并很可能发出更少的警告。
北京北大青鸟学校老师介绍,无论在哪种情况下,编译器在生成字节码时都会生成强制类型转换,所以生成的字节码在每种情况下都不会比没有泛型时更不安全。如果您设法通过使用原始类型或类文件来破坏类型安全,就会得到与不使用泛型时得到的相同的 ClassCastException 或 ArrayStoreException。(北大青鸟课程)
已检查集合
作为从原始集合类型迁移到泛型集合类型的帮助,集合框架添加了一些新的集合包装器,以便为一些类型安全bug提供早期警告。就像 Collections.unmodifiableSet() 工厂方法用一个不允许任何修改的 Set 包装一个现有 Set 一样,Collections.checkedSet()(以及 checkedList() 和 checkedMap())工厂方法创建一个包装器(或者视图)类,以防止您将错误类型的变量放在集合中。(北大青鸟课程)
checkedXxx() 方法都接受一个类常量作为参数,所以它们可以(在运行时)检查这些修改是允许的。典型的实现可能像下面这样:
public class Collections {
public static <E> Collection<E> checkedCollection(Collection<E> c, Class<E> type ) {
return new CheckedCollection<E>(c, type);
}
private static class CheckedCollection<E> implements Collection<E> {
private final Collection<E> c;
private final Class<E> type;
CheckedCollection(Collection<E> c, Class<E> type) {
this.c = c;
this.type = type;
}
public boolean add(E o) {
if (!type.isInstance(o))
throw new ClassCastException();
else
return c.add(o);
}
}
} (北大青鸟课程)
北京北大青鸟学校提供