Java 泛型详解

来源:互联网 发布:数据库 锁定客户群 编辑:程序博客网 时间:2024/06/05 23:31

首先在没有泛型之前,一旦把一个对象丢进java集合中,集合就会忘记对象的类型,把所有对象当成Object类型来处理。当程序从集合中取出对象时,就需要进行强制类型转换,这种强制类型转换不仅代码臃肿,而且容易引起ClassCastException异常。

[java] view plaincopyprint?
  1. public class ListErr  
  2. {  
  3.     public static void main(String[] args)   
  4.     {  
  5.         //创建一个只想保存字符串的List集合  
  6.         List strList = new ArrayList();  
  7.         strList.add("Struts2权威指南");  
  8.         strList.add("基于J2EE的Ajax宝典");  
  9.         strList.add("轻量级J2EE企业应用实战");  
  10.         //”不小心“把一个Integer对象”丢进"了集合  
  11.         strList.add(5);  
  12.         for (int i = 0; i < strList.size() ; i++ )  
  13.         {  
  14.             //因为List里取出的全部是Object,所以必须强制类型转换  
  15.             //最后一个元素将出现ClassCastException异常  
  16.             String str = (String)strList.get(i);  
  17.         }  
  18.     }  
  19. }  

[java] view plaincopyprint?
  1. 为了解决这个问题,在1.5前都采用,创建个List对象的方法,但每遇到个集合都要建个对象,eg  
  2.   
  3.     class StrList  
  4.     {  
  5.         private List strList = new ArrayList();  
  6.         //定义StrList的add方法  
  7.         public boolean add(String ele)  
  8.         {  
  9.             return strList.add(ele);  
  10.         }  
  11.         //重写get方法,将get方法的返回值类型改为String类型  
  12.         public String get(int index)  
  13.         {  
  14.             return (String)strList.get(index);  
  15.         }  
  16.         public int size()  
  17.         {  
  18.             return strList.size();  
  19.         }  
  20.     }  

[java] view plaincopyprint?
  1. public class CheckType  
  2. {  
  3.     public static void main(String[] args)   
  4.     {  
  5.         //创建一个只想保存字符串的List集合  
  6.         StrList strList = new StrList();  
  7.         strList.add("Struts2权威指南");  
  8.         strList.add("基于J2EE的Ajax宝典");  
  9.         strList.add("轻量级J2EE企业应用实战");  
  10.         //下面语句不能把Integer对象“丢进”集合中,将引起编译异常  
  11.         strList.add(5);  
  12.         System.out.println(strList);  
  13.         for (int i = 0; i < strList.size() ; i++ )  
  14.         {  
  15.             //因为StrList里元素的类型就是String类型,所以无需强制类型转换  
  16.             String str = strList.get(i);  
  17.         }  
  18.     }  
  19. }  
[java] view plaincopyprint?
  1. 有了泛型就方便了,eg  
  2.   
  3.     public class GenericList  
  4.     {  
  5.         public static void main(String[] args)   
  6.         {  
  7.             //创建一个只想保存字符串的List集合  
  8.             List<String> strList = new ArrayList<String>();  
  9.             strList.add("Struts2权威指南");  
  10.             strList.add("基于J2EE的Ajax宝典");  
  11.             strList.add("轻量级J2EE企业应用实战");  
  12.             //下面代码将引起编译错误  
  13.             strList.add(5);  
  14.             for (int i = 0; i < strList.size() ; i++ )  
  15.             {  
  16.                 //下面代码无需强制类型转换  
  17.                 String str = strList.get(i);  
  18.             }  
  19.         }  
  20.     }  

当创建带泛型的自定义类时,在定义该类构造器时,构造器名还是和类名一样,不要增加泛型声明。

从泛型类派生子类,接口,父类不能包含类型形参。

下面例子就是错误的。

public class A extends B<T>{},

使用类型通配符“?’”, 它可以匹配任何类型,

public void test(List <?>){}


[html] view plaincopyprint?
  1. 使用时注意:List<String>不是List<Object>子类  
  2.   
  3. 特殊的泛型(带类型通配符和类型上限),eg  
  4.   
  5.     public class Apple<T extends Number>  
  6.     {  
  7.         T col;  
  8.           
  9.         public static void main(String[] args)  
  10.         {  
  11.             Apple<Integer> ai = new Apple<Integer>();  
  12.             Apple<Double> ad = new Apple<Double>();  
  13.             //下面代码将引起编译异常  
  14.             //因为String类型传给T形参,但String不是Number的子类型。  
  15.             Apple<String> as = new Apple<String>();  
  16.               
  17.         }  
  18.     }  
  19.   
  20. java泛型不支持泛型数组(List<String> aa=new ArrayList<String>[10];),因为java泛型的设计原则是没有unchecked警告就没有ClassCastExcepiton. 我建议大家遇到集合数组等的时候,自己来检验数据的类型,eg  
  21.   
  22.     public class test {  
  23.         public static void main(String[] args) {  
  24.             ArrayList[] aa = new ArrayList[10];  
  25.             List<Integer> li = new ArrayList<Integer>();  
  26.             li.add(3);  
  27.             ((Object[]) aa)[1] = li;  
  28.             Object target = aa[1].get(0);  
  29.             if (target instanceof Integer) {  
  30.                 Integer s = (Integer) target;  
  31.                 System.out.println(s);  
  32.             }  
  33.         }  
  34.     }  
  35.   
  36. 由于java的泛型只是编译时做下检验,大家不要想的过于强大,他的最大作用只是增强代码的可读性,别的方面也没见多大的作用。  

什么时候写泛型?有什么好处?

最简单的体现,只要使用到了带有<>的类和接口,就指定具体对象类型。

 

泛型的好处:

1,  将运行时出现的ClassCastException问题,再编译时期给解决了。运行就安全了。

2,  避免了强制转换的麻烦。

 

所以泛型就是JDK1.5后出现的一个安全机制。


泛型的理解?

首先在没有泛型之前,一旦把一个对象丢进java集合中,集合就会忘记对象的类型,把所有对象当成Object类型来处理。

         当程序从集合中取出对象时,就需要进行强制类型转换,这种强制类型转换不仅代码臃肿,而且容易引起ClassCastException异常。

         1,泛型就是传参数。

2,泛型替代了Object。


什么是泛型的擦除和补偿?

泛型是编译时期的安全机制。

         编译时,通过泛型机制,编译器多了多元素类型进行检查的步骤。

         如果检查通过,产生的class文件时不带有泛型的:也就是泛型的擦除。

 

         泛型的补偿:在对元素存储的时候,可以完成类型的判断。

                                     可是在对元素取出的时候,怎么用指定的类型来接收呢?

                                     JVM运行时,会获取元素的类型,并用该类型对元素进行转换即可。


什么时候使用泛型类?

当类中要操作的引用数据类型不确定的时候,以前使用的是共性类型Object,

现在可以使用泛型来解决。


什么时候使用泛型方法?

当方法操作的引用数据类型不确定的时候,就使用泛型方法。

 

如果方法是静态的,是无法访问类上定义的泛型的。

如果该方法还需要泛型。

必须将泛型定义在方法上。


泛型的限定。

如果要对操作的类型进行限定,只操作一部分类型时,可以使用泛型的高级功能。

?extends E:可以接收E类型和E的子类型。这叫泛型的上限。

?super E:可以接收E类型或E的父类型。这叫泛型的下限。


什么时候会用? extends E 呢?(往集合中添加集合的时候经常使用)

一般在存储具体引用类型时,使用这种情况。

因为存储E类型或者E类型的子类型,在取出的时候都可以用E类型来操作这些元素。

这时可以保证类型是安全的。


下限什么时候用?

从集合中取出对象进行操作时,可以使用下限。

例如:比较器。无论集合中的元素对象的类型是什么,只要比较器的指定的类型可以接收这些对象完成比较,就可以了。

所以比较器的类型,可以是集合中当前元素的类型,也可以是该元素类型的父类型。


泛型使用的误区:

1,  凡是安全的都特别严格。一定要保证座左右两边一致。

2, 不能操作特有对象。

参数定义的集合类型是一个范围,而接受的实际参数是以一个实体,该实体肯定会指定该范围中的某一个具体类型。而该类型是创建容器时指定的,到底是哪种类型该方法是不确定的,那么就不可以在该方法内,进行具体类型对象的定义和操作。

 建议定义泛型时,左右两边一定要一致。如果不一致要保证一点,左边在声明时可以声明一个类型范围,右边在实例化时指定的具体类型必须是左边类型范围中的一种。

0 0
原创粉丝点击