Java 泛型

https://www.bilibili.com/video/BV1Kb411W75N

泛型的概念

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

例如,Arraylist,当不指定泛型时可以传入任意类型的值,但我们想固定它里面装的数据的类型,就可以使用泛型:ArrayList<Integer> list = new ArrayList<Integer>();,这里的<Integer>就是泛型。泛型是jdk5.0新增的特性。

在集合中使用泛型

import java.util.*;

public class GenericTest {
    public static void main(String[] args) {
        GenericTest genericTest = new GenericTest();
        genericTest.test3();
    }

    // 在集合中使用泛型之前的情况:
    public void test1() {
        ArrayList list = new ArrayList();
        // 需求:存放学生的成绩
        list.add(78);
        list.add(76);
        list.add(89);
        list.add(88);
        // 问题一:类型不安全
//        list.add("Tom");

        for (Object score : list) {
            // 问题二:强转时,可能出现ClassCastException
            int stuScore = (int) score;
            System.out.println(stuScore);
        }
    }

    // 在集合中使用泛型的情况:以ArrayList为例
    public void test2() {
        ArrayList<Integer> list = new ArrayList<Integer>();

        list.add(78);
        list.add(87);
        list.add(99);
        list.add(65);
        // 编译时就会进行类型检查,保证数据的安全
//        list.add("Tom");

        // 方式一:
//        for (Integer score : list) {
//            // 避免了强转操作
//            int stuScore = score;
//
//            System.out.println(stuScore);
//        }

        // 方式二:
        Iterator<Integer> iterator = list.iterator();
        while (iterator.hasNext()) {
            int stuScore = iterator.next();
            System.out.println(stuScore);
        }
    }
}

总结:

  1. 集合接口或集合类在jdk5.0时都修改为带泛型的结构。
  2. 在实例化集合类时,可以指明具体的泛型类型。
  3. 指明完以后,在集合类或接口中凡是定义类或接口时,内部结构(比如:方法、构造器、属性等)使用到类的泛型的位置,都指定为实例化时的泛型类型。
    比如:add(E e) => 实例化以后:add(Integer e)
  4. 注意点:泛型的类型必须是类,不能是基本数据类型。需要用到基本数据类型的位置,拿包装类替换
  5. 如果实例化时,没有指明泛型的类型。默认类型为 java.lang.Object 类型。

自定义泛型结构

自定义泛型类和泛型接口

定义泛型类:public class Order<T>

定义泛型接口:public interface aa<T>

定义完泛型类和泛型接口后,其内部结构就可以使用相应的泛型。

注意点:

  • 泛型不同的引用不能相互赋值
  • 静态方法中不能使用类的泛型
  • 异常类不能声明为泛型类

自定义泛型方法

泛型方法:在方法中出现了泛型的结构,泛型参数与类的泛型参数没有任何关系。

泛型方法和所属的类是不是泛型类也没有关系

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

声明泛型方法举例:

public static <E> List<E> copyFromArrayToList(E[] arr) {
    ArrayList<E> list = new ArrayList<>();

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

泛型的其它注意点

泛型与类的继承

若A是B的父类:

G<A>和G<B>二者没有子父类关系,是并列关系。

A<G>和B<G>是子父类关系,A<G>是B<G>的父类。

泛型通配符

若A是B的父类,G<A>和G<B>二者共同的父类是G<?>(通配符)。

使用通配符后的集合无法写入数据,只能写入null。可读取数据,但读取出来的数据类型是Object。

有限制条件的通配符

<? extends Person>: ≤ Person 类

<? super Person>: ≥ Person 类

上一篇:【Java】ArrayList基础语法


下一篇:Java ArrayList 类