美文网首页
Java基础篇之泛型详解下篇

Java基础篇之泛型详解下篇

作者: 小墨哈 | 来源:发表于2017-03-16 21:05 被阅读29次

5.通配符
为了引出通配符的概念,先看如下代码:

List<Integer> ex_int= new ArrayList<Integer>();    
List<Number> ex_num = ex_int; //非法的  

上述第2行会出现编译错误,因为Integer虽然是Number的子类,但List<Integer>不是List<Number>的子类型。

假定第2行代码没有问题,那么我们可以使用语句ex_num.add(newDouble())在一个List中装入了各种不同类型的子类,这显然是不可以的,因为我们在取出List中的对象时,就分不清楚到底该转型为Integer还是Double了。

因此,我们需要一个在逻辑上可以用来同时表示为List<Integer>List<Number>的父类的一个引用类型,类型通配符应运而生。在本例中表示为List<?>即可。下面这个例子也说明了这一点,注释已经写的很清楚了。

public static void main(String[] args) {  
   FX<Number> ex_num = new FX<Number>(100);  
   FX<Integer> ex_int = new FX<Integer>(200);  
   getData(ex_num);  
   getData(ex_int);//编译错误  
}  
 
public static void getData(FX<Number> temp) { //此行若把Number换为“?”编译通过  
   //do something...  
}  
     
public static class FX<T> {  
   private T ob;   
   public FX(T ob) {  
       this.ob = ob;  
   }  
}  

6.上下边界
看了下面这个上边界的例子就明白了,下界FX<? supers Number>的形式就不做过多赘述了。

public static void main(String[] args) {  
    FX<Number> ex_num = new FX<Number>(100);  
    FX<Integer> ex_int = new FX<Integer>(200);  
    getUpperNumberData(ex_num);  
    getUpperNumberData(ex_int);  
}  
  
public static void getUpperNumberData(FX<? extends Number> temp){  
      System.out.println("class type :" + temp.getClass());  
}  
      
public static class FX<T> {  
    private T ob;   
    public FX(T ob) {  
    this.ob = ob;  
    }  
}  

7.泛型的好处
**(1)类型安全 **
通过知道使用泛型定义的变量的类型限制,编译器可以更有效地提高Java程序的类型安全。
(2)消除强制类型转换
消除源代码中的许多强制类型转换。这使得代码更加可读,并且减少了出错机会。所有的强制转换都是自动和隐式的。
(3)提高性能

Lits list1 = new ArrayList();  
list1.add("CSDN_SEU_Cavin ");  
String str1 = (String)list1.get(0);  

List<String> list2 = new ArrayList<String>();  
list2.add("CSDN_SEU_Cavin ");  
String str2 = list2.get(0);  

对于上面的两段程序,由于泛型所有工作都在编译器中完成,javac编译出来的字节码是一样的(只是更能确保类型安全),那么何谈性能提升呢?是因为在泛型的实现中,编译器将强制类型转换插入生成的字节码中,但是更多类型信息可用于编译器这一事实,为未来版本的 JVM 的优化带来了可能。

8.泛型使用的注意事项

(1)泛型的类型参数只能是类类型(包括自定义类),不能是简单类型。
(2)泛型的类型参数可以有多个。
(3)不能对确切的泛型类型使用instanceof操作。如下面的操作是非法的,编译时会出错。

if(ex_num instanceof FX<Number>){   
}  

(4)不能创建一个确切的泛型类型的数组。下面使用Sun的一篇文档的一个例子来说明这个问题:

List<String>[] lsa = new List<String>[10]; // Not really allowed.    
Object o = lsa;    
Object[] oa = (Object[]) o;    
List<Integer> li = new ArrayList<Integer>();    
li.add(new Integer(3));    
oa[1] = li; // Unsound, but passes run time store check    
String s = lsa[1].get(0); // Run-time error: ClassCastException.    

这种情况下,由于JVM泛型的擦除机制,在运行时JVM是不知道泛型信息的,所以可以给 oa[1]赋上一个ArrayList<Integer>而不会出现异常,但是在取出数据的时候却要做一次类型转换,所以就会出现ClassCastException,如果可以进行泛型数组的声明,上面说的这种情况在编译期将不会出现任何的警告和错误,只有在运行时才会出错。
下面采用通配符的方式是被允许的:

List<?>[] lsa = new List<?>[10]; // OK, array of unbounded wildcard type.    
Object o = lsa;    
Object[] oa = (Object[]) o;    
List<Integer> li = new ArrayList<Integer>();    
li.add(new Integer(3));    
oa[1] = li; // Correct.    
Integer i = (Integer) lsa[1].get(0); // OK 

相关文章

  • Java基础篇之泛型详解下篇

    5.通配符为了引出通配符的概念,先看如下代码: 上述第2行会出现编译错误,因为Integer虽然是Number的子...

  • 详解Java泛型之3——十分钟理解泛型擦除

    前面我们介绍了泛型以及通配符的基础概念,可以参考文章: 详解Java泛型之1——入门泛型必懂的知识点[https:...

  • 详解Java泛型之2——详解通配符

    上一篇文章中我们介绍了泛型的基础知识点,详情请参考文章: 详解Java泛型之1——入门泛型必懂的知识点[https...

  • 详解Java泛型之4——一个例子理解泛型带来的好处

    前面我介绍了关于泛型、通配符以及泛型擦除的相关知识点,大家可以参考以下文章: 详解Java泛型之1——入门泛型必懂...

  • Java基础篇之泛型详解上篇

    1.为什么需要泛型 泛型在Java中有很重要的地位,网上很多文章罗列各种理论,不便于理解,本篇将立足于代码介绍、总...

  • JAVA 基础之泛型详解

    参考文章:https://blog.csdn.net/s10461/article/details/5394109...

  • 泛型程序设计

    诚心推荐这一篇文章更好 java 泛型详解 泛型程序设计 泛型意味着编写的代码可以被不同类型重用 ArrayLis...

  • Java基础之泛型

    Java基础之泛型 泛型基本介绍 简单介绍在jdk1.6之前,还没有使用到泛型,Java类型分为原始类型、复杂类型...

  • 泛型,复习

    Java泛型详解:和Class的使用。泛型类,泛型方法的详细使用实例 - LZJWXJ树袋熊 - CSDN博客

  • Java 泛型(Generic)

    本文在Java 泛型详解的基础上添加注释和增补 泛型的目的 泛型的主要目的之一就是用来指定容器要持有什么类型的对象...

网友评论

      本文标题:Java基础篇之泛型详解下篇

      本文链接:https://www.haomeiwen.com/subject/xwqsnttx.html