现在的位置: 首页 > 综合 > 正文

Java 5.0泛型编程之泛型类型(2)

2018年04月27日 ⁄ 综合 ⁄ 共 2269字 ⁄ 字号 评论关闭
 理解泛型类型

  本段将对泛型类型的使用细节做进一步的探讨,以尝试说明下列问题:

  不带类型参数的使用泛型的后果

  参数化类型的体系

  一个关于编译期泛型类型的类型安全的漏洞和一个用于确保运行期类型安全的补丁

  为什么参数化类型的数组不是类型安全的

  未经处理的类型和不被检查的警告

  即使被重写的Java集合类带来了泛型的好处,在使用他们的时候您也不被要求说明类型变量。一个不带类型变量的泛型类型被认为是一个未经处理的类型(raw type)。这样,5.0版本以前的java代码仍然能够运行:您显式的编写所有类型转换就像您已经这样写的一样,您可能会被一些来自编译器的麻烦所困扰。查看下列存储不同类型的对象到一个未经处理的List:

List l = new ArrayList();
l.add("hello");  
l.add(new Integer(123));
Object o = l.get(0);

这段代码在java1.4下运行得很好。如果您用java5.0来编译它,javac编译了,但是会打印出这样的“抱怨”:

Note: Test.java uses unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.

  如果我们加入-Xlint参数后重新编译,我们会看到这些警告:

Test.java:6: warning: [unchecked]
    unchecked call to add(E) as a member of the raw type java.util.List
        l.add("hello");  
         ^
Test.java:7: warning: [unchecked]
    unchecked call to add(E) as a member of the raw type java.util.List
        l.add(new Integer(123));

         ^

  编译在add()方法的调用上给出了警告,因为它不能够确信加入到list中的值具有正确的类型。它告诉我们说我们使用了一个未经处理的类型,它不能验证我们的代码是类型安全的。注意,get()方法的调用是没有问题的,因为能够被获得的元素已经安全的存在于list中了。

  如果您不想使用任何的java5.0的新特性,您可以简单的通过带-source1.4标记来编译他们,这样编译器就不会再“抱怨”了。如果您不能这样做,您可以忽略这些警告,通过使用一个“@SuppressWarnings("unchecked")”注解(查看本章的4.3节)隐瞒这些警告信息或者升级您的代码,加入类型变量描述。[2]下列示例代码,编译的时候不再会有警告但仍然允许您往list中放入不同的类型的对象。

List<Object> l = new ArrayList<Object>();
l.add("hello");  
l.add(123);              // autoboxing
Object o = l.get(0);

  参数化类型的体系

  参数化类型有类型体系,就像一般的类型一样。这个体系基于对象的类型,而不是变量的类型。这里有些例子您可以尝试:

ArrayList<Integer> l = new ArrayList<Integer>();
List<Integer> m = l;                            // okay
Collection<Integer> n = l;                      // okay
ArrayList<Number> o = l;                        // error
Collection<Object> p = (Collection<Object>)l;   // error, even with cast

一个List<Integer>是一个Collection<Integer>,但不是一个List<Object>。这句话不容易理解,如果您想理解为什么泛型这样做,这段值得看一下。考察这段代码:

List<Integer> li = new ArrayList<Integer>();
li.add(123);

// The line below will not compile.  But for the purposes of this
// thought-experiment, assume that it does compile and see how much
// trouble we get ourselves into.
List<Object> lo = li;  

// Now we can retrieve elements of the list as Object instead of Integer
Object number = lo.get(0);

// But what about this?
lo.add("hello world");

// If the line above is allowed then the line below throws ClassCastException
Integer i = li.get(1);  // Can't cast a String to Integer!

这就是为什么List<Integer>不是一个List<Object>的原因,虽然List<Integer>中所有的元素事实上是一个Object的实例。如果允许转换成List<Object>,那么转换后,理论上非整型的对象也将被允许添加到list中

抱歉!评论已关闭.