//泛型类的内部类可以访问到其外围类的类型参数。 //当你在一个泛型类中嵌套另一个泛型类时,最好为它们的类型参数设置不同的名字,即使那个嵌套类是静态的也应如此。 class LinkedList<E> { /* 访问外围类的类型参数 private Node head = null; private class Node { E value; Node next; Node(E value, Node next) { this.value = value; this.next = next; head = this; } } public void add(E e) { new Node(e); } public void dump() { for (Node n = head; n != null; n = n.next) System.out.print(n.value + " "); } */ //使用静态类 private Node<E> head = null; private static class Node<T> { T value; Node<T> next; Node(T value, Node<T> next) { this.value = value; this.next = next; } } public void add(E e) { head = new Node<E>(e, head); } public void dump() { for (Node<E> n = head; n != null; n = n.next) System.out.print(n.value + " "); } }
//一个原生类型很像其对应的参数化类型,但是它的所有实例成员都要被替换掉, //而替换物就是这些实例成员被擦除掉对应部分参数类型之后剩下的东西。 //具体地说,在一个实例方法声明中出现的每个参数化的类型都要被其对应的原生部分所取代。 //原生类型List 和参数化类型List<Object>是不一样的。 //如果使用了原生类型,编译器不会知道在List 允许接受的元素类型上是否有任何限制,它会允许你添加任何类型的元素到List 中。 //List<?>是一种特殊的参数化类型,被称为通配符类型(wildcard type)。 //像原生类型List 一样,编译器也不会知道它接受哪种类型的元素,但是因为List<?>是一个参数化类型, //从语言上来说需要更强的类型检查。为了避免出现ClassCastException 异常,编译器不允许 //你添加除null 以外的任何元素到一个类型为List<?>的list 中。 //原生类型的成员被擦掉,是为了模拟泛型被添加到语言中之前的那些类型的行为。 //如果你将原生类型和参数化类型混合使用,那么便无法获得使用泛型的所有好处, //而且有可能产生让你困惑的编译错误。另外,原生类型和以Object为类型参数的参数化类型也不相同。 @SuppressWarnings("rawtypes") Pair p = new Pair<Object> (23, "skidoo"); System.out.println(p.first() + " " + p.last()); //编译错误:因为Pair p被声明为原生类型,擦除了所有的<>参数化类型信息,stringList()方法返回值类型为List,而不是List<String>。 //for (String s : p.stringList()) for (Object s : p.stringList()) System.out.print(s + " "); class Pair<T> { private final T first; private final T last; public Pair(T first, T last) { this.first = first; this.last = last; } public T first() { return first; } public T last() { return last; } public List<String> stringList() { return Arrays.asList(String.valueOf(first), String.valueOf(last)); } }