您的位置:首页 > 职场人生

黑马程序员——Java泛型

2016-01-29 21:43 555 查看
------<a href="http://www.itheima.com" target="blank">Java培训、Android培训、iOS培训、.Net培训</a>、期待与您交流! -------


泛型

泛型是对Java语言的类型系统的一种扩展,以支持创建可以按类型进行参数化的类。

没有使用泛型时,只要是对象,不管是什么类型的对象,都可以存储进同一个集合中。使用泛型集合,可以将一个集合中的元素限定为一个特定类型,集合中只能存储同一个类型的对象,这样更安全;并且当从集合获取一个对象时,编译器也可以知道这个对象的类型,不需要对对象进行强制类型转换,更方便。

示例:

[java] view
plain copy

 





public static void main(String[] args) throws Exception {  

     Constructor<String> constructor = String.class.getConstructor(StringBuffer.class);  

     String str = constructor.newInstance( new StringBuffer("abc" ));  

     System. out.println(str.charAt(2));  

      //结果:c  

引入泛型后,创建实例对象时就不需要类型转换了。


泛型的内部原理

泛型时提供给javac编译器使用的,可以限定集合中的输入类型,让编译器挡住源程序中的非法输入。但是,编译器编译带类型说明的集合时会去掉“类型”信息,目的就是使程序运行效率不受影响。因此,对于参数化的泛型类型,getClass()方法的返回值和原始类型完全一样。

[java] view
plain copy

 





ArrayList<String> collection1 = new ArrayList<String>();  

ArrayList collection2 = new ArrayList();  

System. out.println(collection1.getClass() == collection2.getClass());  

 //结果:true  

由于编译生成的字节码会取缔哦泛型的类型信息,只要能跳过编译器,就可以往某个泛型集合中加入其他类型的数据。

示例:用反射得到集合,再调用其add方法

[java] view
plain copy

 





 public static void main(String[] args) throws Exception {  

      ArrayList<Integer> collection1 = new ArrayList<Integer>();  

      collection1.getClass().getMethod( "add",Object.class).invoke(collection1, "abc");  

      System. out.println(collection1.get(0));  

}  

ArrayList<E>类定义和ArrayList<Integer>类引用中涉及如下术语:

整个称为ArrayList<E>泛型类型

ArrayList<E>中的E称为类型变量或类型参数

整个ArrayList<Integer>称为参数化的类型

ArrayList<Integer>中的Integer称为类型参数的实例或实际类型参数

ArrayList<Integer>中的<>念着typeof

ArrayList称为原始类型

参数化类型与原始类型的兼容性:

参数化类型可以引用一个原始类型的对象,编译报告警告,例如:Collection <String> c = new Vector();//考虑到对以前代码的兼容性,编译器是可以通过的

原始类型可以引用一个参数化类型的对象,编译报告警告,例如:Collection  c = new Vector<String>();//原来的方法接收一个集合参数,新的类型也要能传进去

参数化类型不考虑类型参数的继承关系:

Vector<String> v = new Vector<Object>();    //错误!可以的话,那么以后从v中取出的对象当作String用,而v实际指向的对象中可以加入任意的类型对象

Vector<Object> v = new Vector<String>();    //错误!可以的话,那么以后可以向v中加入任意的类型对象,而v实际指向的集合中只能装String类型的对象

编译器不允许创建泛型变量的数组。即在创建数组实例时,数组的元素不能使用参数化的类型。

例如:Vector<Integer> vectorList[] = new Vector<Integer>[10];     //错误


泛型的通配符扩展应用

问题:

定义一个方法,该方法用于打印出任意参数化类型的集合中的所有数据,该方法如何定义呢?

如果将printCollection中的参数设置为Collection<Object>类型,那么传入参数的时候,如果参数化的类型是其他类型,就会报错。

[java] view
plain copy

 





       public static void main(String[] args) {  

             ArrayList<Integer> collection = new ArrayList<Integer>();  

             printCollection(collection);  

      }  

   

 //public static void printCollection(Collection<Object> collection){}  

  

 public static void printCollection(Collection<?> collection){  

             //collection.add(1);//报错  

            System. out.println(collection.size());  

            for(Object obj : collection){  

                  System. out.println(obj);  

            }  

      }  

Java1.5中使用?通配符可以引用其他各种参数化的类型,?通配符定义的变量主要用作引用。此时,printCollection方法中可以调用与参数化无关的方法,不能调用与参数化有关的方法。上面的示例Collection类中的add(E e)方法就与参数化有关,不能调用。size()方法与参数化无关就可以调用。

限定通配符的上边界:

正确:Vector<? extends Number> x = new Vector<Integer>();

错误:Vector<? extends Number> x = new Vector<String>();

限定通配符的下边界:

正确:Vector<? super Integer> x = new Vector<Number>();

错误:Vector<? super Integer> x = new Vector<Byte>();
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: