泛型

1.泛型的概念

所谓泛型,就是允许在定义类、接口时通过一个标识表示类中某个属性的类型或者是某个方法的返回值及参数类型。这个类型参数将在使用时(例如,继承或实现这个接口,用这个类型声明变量、创建对象时确定(即传入实际的类型参数,也称为类型实参)。

 2、泛型的声明

  interface List<T> 和 class GenTest<K,V>

  其中,T,K,V不代表值,而是表示类型。这里使用任意字母都可以。 常用T表示,是Type的缩写。

3、泛型的实例化

一定要在类名后面指定类型参数的值(类型)。如:

  List<String> strList = new ArrayList<String>();

  Iterator<Customer> iterator = customers.iterator();

    3.1:T只能是类,不能用基本数据类型填充。但可以使用包装类填充

    3.2:把一个集合中的内容限制为一个特定的数据类型,这就是generics背后的核心思想

4、泛型类和泛型接口注意点

  如果定义了泛型类,实例化没有指明类的泛型,则认为此泛型类型为Object类型。最好在实例化时就指明泛型类

  子类在继承带泛型的父类时,指明了泛型类型。则实例化子类对象时,不再需要指明泛型。

   泛型不同的引用不能相互赋值。

  类的泛型是实例化时指定,但是类的静态方法是在类加载时,因此在静态方法 中不能使用类的泛型

  异常类不能是泛型的

  不能使用new E[]。但是可以:E[] elements = (E[]) new Object[capacity];

  父类有泛型,子类可以选择保留泛型也可以选择指定泛型类型: 

  1.子类不保留父类的泛型:按需实现 

    没有类型 擦除 

    具体类型 

  2.子类保留父类的泛型:泛型子类 

    全部保留 

    部分保留

5、泛型方法

  不是方法中使用了泛型就是。而是在方法中出现了泛型的参数,泛型参数与类的泛型参数没有任何关系。

  泛型方法与所属的类是不是泛型类没有任何关系。泛型方法在调用时,指明泛型参数的类型。

  泛型方法,可以声明为静态的。原因:泛型参数是在调用方法时确定的。并非在实例化类时确定。

  [访问权限] <泛型> 返回类型 方法名([泛型标识 参数名称]) 抛出的异常

 

public static <E>  List<E> copyFromArrayToList(E[] arr){

        ArrayList<E> list = new ArrayList<>();

        for(E e : arr){
            list.add(e);
        }
        return list;

    }
}

 

6、应用场景举例:

 

      对于通用操作,利用泛型会非常方便。

7、泛型在继承上的体现

      虽然类A是类B的父类,但是G<A> 和G<B>二者不具备子父类关系,二者是并列关系。
        Object obj = null;
        String str = null;
        obj = str;

        Object[] arr1 = null;
        String[] arr2 = null;
        arr1 = arr2;
        

        List<Object> list1 = null;
        List<String> list2 = new ArrayList<String>();
        //此时的list1和list2的类型不具子父类关系
        //编译不通过

       补充:类A是类B的父类,A<G> 是 B<G> 的父类

        List<String> list2 = null;
        ArrayList<String> list3 = null;

        list2 = list3;

8、通配符

  通配符:?
         类A是类B的父类,G<A>和G<B>是没关系的,二者共同的父类是:G<?>
 @Test
    public void test3(){
        List<Object> list1 = null;
        List<String> list2 = null;

        List<?> list = null;

        list = list1;
        list = list2;
        //编译通过
     print(list2);
     print(list1);
} public void print(List<?> list){ Iterator<?> iterator = list.iterator(); while(iterator.hasNext()){ Object obj = iterator.next(); System.out.println(obj); } }

对于List<?>:

  添加(写入):就不能向其内部添加数据。除了添加null之外。

  获取(读取):允许读取数据,读取的数据类型为Object。
限制条件的通配符的使用。
        ? extends A:  小于等于的关系,?可以为A或者A的子类
                G<? extends A> 可以作为G<A>和G<B>的父类,其中B是A的子类
        ? super A:    大于等于的关系,?可以看作A或者A的父类
                G<? super A> 可以作为G<A>和G<B>的父类,其中B是A的父类
        List<? extends Person> list1 = null;
        List<? super Person> list2 = null;

        List<Student> list3 = new ArrayList<Student>();
        List<Person> list4 = new ArrayList<Person>();
        List<Object> list5 = new ArrayList<Object>();

        list1 = list3;
        list1 = list4;
//        list1 = list5;

//        list2 = list3;
        list2 = list4;
        list2 = list5;

        //读取数据:
        list1 = list3;
        Person p = list1.get(0);
        //编译不通过
        //Student s = list1.get(0);

        list2 = list4;
        Object obj = list2.get(0);
        ////编译不通过
//        Person obj = list2.get(0);

 

posted @ 2020-05-04 23:31  kkzhang  阅读(614)  评论(0编辑  收藏  举报