2

我注意到泛型类的原始类型可以采用(指向)泛型类的所有不同变体,并且泛型类的所有不同变体都可以采用(指向)泛型类的原始类型。为什么 Java 泛型会有这样的行为?纯粹是因为兼容旧版本的Java吗?

例子:

//Main.java
public class Main {

    /**
     * @param args
     */
    public static void main(String[] args) {

    List listRaw = new ArrayList();
    List<Student> listQualified = new ArrayList<Student>();
    List<?> listUnbounded = new ArrayList<Student>();
    List<? extends Student> listUpBounded = new ArrayList<Student>();
    List<? super Student> listDownBounded = new ArrayList<Student>();

    // List raw type can take all different variations of List
    List rawList1 = listRaw;
    List rawList2 = listQualified;
    List rawList3 = listUnbounded;
    List rawList4 = listUpBounded;
    List rawList5 = listDownBounded;

    // All different variations of List can take List raw type
    listRaw = rawList1;
    listQualified = rawList2;
    listUnbounded = rawList3;
    listUpBounded = rawList4;
    listDownBounded = rawList5;

    }

}

//People.java
public class People {

    public static class Student extends People {
    }

    public class HistoryStudent extends Student {
    }

    public class MathStudent extends Student {
    }
}
4

2 回答 2

4

Sun 工程师面临的主要挑战之一是保持向后兼容性。例如,如果您无法分配:

List list = new ArrayList<Student>();

那么,您将无法使用较旧的库方法。IE:

List org.apache.commons.collections.ListUtils.intersection(List arg0, List arg1)

还要记住这些类型在运行时消失,如http://docs.oracle.com/javase/tutorial/java/generics/erasure.html中所述

于 2012-07-09T22:20:13.367 回答
1

是的。实际上泛型是在 java 5 中添加的,并且该语言必须保持与旧版本的运行时兼容性。这种折衷是有效的,因为一旦代码被编译(类型 ereasure)到 .class 中,实际上泛型信息就会消失,即使您可以通过反射获得信息,无论某些方法是否接受泛型类型参数。如果您编译与您编写的代码类似的代码,它可以正常工作,但通常编译器会警告您您正在使用“原始”类型。

于 2012-07-09T22:10:57.833 回答