黑马程序员_<<基础加强--1.5新特性(泛型)(下)>>

来源:互联网 发布:pc6软件 编辑:程序博客网 时间:2024/06/06 03:24

--------------------ASP.Net+Android+IOS开发、.Net培训、期待与您交流! --------------------



1. 泛型

      1.概述

         泛型就是为了提高安全性,接口,类和方法上都可以使用泛型,特别是集合中常用到,对于泛型,是在编译器起到作用,当你存到了与指定的泛型类型不相同的对象,那么编译器会提示错误,但是在运行期,泛型是起不到作用的,下面我们就利用反射存储和指定泛型类型不一样的对象,来验证泛型是在编译器其作用。

 

import java.util.ArrayList;public class FanXing {  public static void main(String[] args) throws Exception {    ArrayList list = new ArrayList();// 这里编译器会给警告,不安全的警告    ArrayList<Integer> list1 = new ArrayList<Integer>();// 这里编译器就不会提示警告了    list1.add(new Integer(12));    list1.add(new Integer(34));    System.out.println("list1=" + list1);    /**     * 利用反射向集合中存储和类型不一样的对象先利用反射获得方法,然后调用方法来进行存储     */    ArrayList.class.getMethod("add", Object.class).invoke(list1, "abc");// true,插入成功    System.out.println("list1=" + list1);  }}结果:list1=[12, 34]list1=[12, 34, abc]


 

从结果可以看出,已经把”abc”存储进去了,所以我们只要跳过了编译器,那么我们就会存储任何对象了。

     2.泛型术语

                  例如:    

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

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

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

         ArrayList<Integer>:中的<>念着typeof

         ArrayList:称为原始类型

 

     3.泛型声明格式

 

           /*前后指定的泛型类型不一样,泛型类型参数不存在继承关系*/

    Collection<Object> con=new ArrayList<String>();//编译失败

    Collection<String> con1=new ArrayList<Object>();//编译失败

    /*可以一遍声明参数类型,一遍不声明*/

    Collection<Object> con2=new ArrayList();//编译成功,有警告

    Collectioncon3=new ArrayList<Object>();//编译成功,有警告

 

 

        泛型集合没有数组类型

          List<String> [] list=newArrayList<String>[10];//编译失败

   

     4.通配符

              4.1通配的使用

                通配符用?表示,表示任意类型

 

        

 import java.util.ArrayList;import java.util.List;public class FanXing {  public static void main(String[] args) throws Exception {     ArrayList<String> list = new ArrayList<String>();// 这里编译器就不会提示警告了    list.add("abc");    list.add("hello");    show(list);    ArrayList<Integer> list1 = new ArrayList<Integer>();// 这里编译器就不会提示警告了    list1.add(new Integer(12));    list1.add(new Integer(34));    show(list1);   }   public static void show(List<?> list) {// ?表示可以接收任何类型的List集合    System.out.println(list);  }}结果:[abc, hello][12, 34]

            4.2上下限

            

        类<?extends  类(A)> :设置上限,?可以是A类对象或者是A的子类对象。

       类<? Super  类(B)> :设置上限,?可以是B类对象或者是A的父类对象。

       例如:

import java.util.ArrayList;import java.util.List;public class FanXing {  public static void main(String[] args) throws Exception {     ArrayList<Integer> list = new ArrayList<Integer>();// 这里编译器就不会提示警告了    list.add(new Integer(12));    list.add(new Integer(34));    show(list);    ArrayList<Object> list1 = new ArrayList<Object>();// 这里编译器就不会提示警告了    list1.add(new Integer(12));    list1.add("abc");    show1(list1);   }  // ?表示可以接收Number的类型或者是NUmber子类的类型的List集合,其他的类型不可以  public static void show(List<? extends Number> list) {    System.out.println(list);  }  // ?表示可以接收Number的类型或者是NUmber父类的类型的List集合,其他的类型不可以  //这里可以知道Number的父类只有Object,所以只能接受Number和Object类型  public static void show1(List<? super Number> list) {    System.out.println(list);  }}结果:[12, 34][12, abc]


 

     5.综合使用

       

   import java.util.HashMap;import java.util.Iterator;import java.util.Set;import java.util.Map;import java.util.Map.Entry;public class FanXing {  public static void main(String[] args) throws Exception {     HashMap<String,Integer> map=new HashMap<String,Integer>();    map.put("java01", 20);    map.put("java02", 22);    map.put("java03", 23);    /*     * 读取HashMap集合,有三种方法,     *  1.读取键集     *  2.读取值集     *  3.读取Map.Entry     *  下面使用第三种读取集合*/    Set<Map.Entry<String,Integer>> entry=map.entrySet();      Iterator<Entry<String, Integer>> it=entry.iterator();       while(it.hasNext()){         Map.Entry<String,Integer> ks=it.next();         System.out.println(ks.getKey()+"="+ks.getValue());       }  } }结果:java02=22java03=23java01=20 

     6.小知识点

          Java中的泛型是模仿的是C++的泛型

     java中的泛型是是在编译期,在运行期间就“擦除了”

     注意事项:

          只有引用类型的才能作为泛型的实际参数类型

           要是int类型会自动装箱成Integer

           但是int[]数组就不会自动装箱,因为本身就是引用类型, 但是其不能作为泛型的实际参数。

     异常泛型,你可以抛出泛型异常,但是获取的时候,catch()处理异常的时候不能是catch(T  e)必须是具体的异常,catch(Exceptione),可以抛出throw (T) e,和throws T

 

      

     7.自定义泛型类

         在方法中使用泛型的时候,定义的时候在方法的返回值前面声明其泛型,<T>为类定义泛型public class 类名<T>{}

       静态方法中不能使用和定义类的时候的泛型,因为对象没有创建的时候就调用了,所以静态方法调用的时候,可以没有对象,但是泛型不知道了,但是你要是使用泛型的话,那么就可定义类的泛型可以分开,不使用同一个泛型。


      详细的可以参考黑马程序员_<<泛型>>

         8.获得方法参数的类型

             通过泛型类型的方法获得方法参数的类型

 

       publicstaticvoidapplyVector(Vector<Date> v1) {}

       publicstaticvoidapplyVector(Vector<Integer> v1) {}

       首先说明;这样写编译器活报错,原因是这不是方法的重载,参数类型都是Vector类型,不能通过用泛型来区分这不是同一类型,这是同一个类型,都是Vector,同时早获取方法的时候,也不能获取Vector<Data>.class或者Vector<Integer>.class类型,只能是Vector.class.

 

import java.lang.reflect.*;import java.util.Date;import java.util.Vector; public class FanXing {  public static void main(String[] args) throws SecurityException,      NoSuchMethodException {    Method method = FanXing.class.getMethod("applyVector", Vector.class);//获得方法    Type[] types = method.getGenericParameterTypes();//获得方法上的泛型类型    ParameterizedType pType = (ParameterizedType) types[0];// 通过Type的子类获取对象,第一个类型    System.out.println(pType.getRawType());// 获取对象的类型    System.out.println(pType.getActualTypeArguments()[0]);    // 获取的是对象中的所有参数,我们知道我们定义的方法只有一个泛型类型,所以取第一个就可以  }   public static void applyVector(Vector<Date> v1) {   } }结果:class java.util.Vectorclass java.util.Date 



--------------------ASP.Net+Android+IOS开发.Net培训、期待与您交流! --------------------


原创粉丝点击