泛型

  • 定义泛型时常用字母 E T K V S U
    • T type表示类型,K,V代表键和值,E代表element

1.1. 类中

格式: 修饰符 class 类名<代表泛型的变量> { }

1.1.1. 案例

  • 定义一个学生类 定义一个属性 age,希望age的类型可以是Integer也可以是String

1.1.2. 代码

  • 1 定义学生类 在类的后面添加泛型 <T> ,在定义age属性和相关getset方法时,就使用T
  • 2 测试 创建2个学生类对象, 分别传入不同的泛型Integer和String

1658647594276

1.2. 可以定义多个泛型,逗号分开

1.2.1. 类代码 两个泛型T 和E

  • T装饰age的类型 E装饰height的类型
//类中定义泛型 <T>
public class Student01<T, E> {

    //这里使用泛型T
    T age;
    E height;

    public T getAge() {
        return age;
    }

    public void setAge(T age) {
        this.age = age;
    }

    public E getHeight() {
        return height;
    }

    public void setHeight(E height) {
        this.height = height;
    }
}

1.2.2. 测试代码

//创建学生对象  传入泛型 具体类型Integer和Double
Student01<Integer, Double> stu01 = new Student01<>();
stu01.setAge(10);
stu01.setHeight(10.5);

//创建学生对象  传入泛型 具体类型String
Student01<String, String> stu02 = new Student01<>();
stu02.setAge("20");
stu02.setHeight("50");

1.3. 方法中(要配合参数使用)

格式:修饰符 <代表泛型的变量> 返回值类型 方法名(参数){ }

1.3.1. 语法练习

1.3.2. 代码

  • 在show方法上定义泛型 ,在参数中 给age定义类型时使用了泛型T
    • 一般配合参数使用,在调用的时候,传入什么类型, T就是什么类型
public class AA {
    //方法中定义的泛型
    //一般配合参数使用,在调用的时候,传入什么类型, T就是什么类型
    public <T> void show(T age) {
        T a = age;
        System.out.println(a);
    }
}

1.3.3. 测试

public class DEmo01 {
    public static void main(String[] args) {
        AA aa = new AA();
        aa.show(10);
        aa.show("20");
        aa.show(10.5);
    }
}

1.4. 接口中(重点)

格式:修饰符 interface 接口名<代表泛型的变量> { }

1.4.1. 接口和实现类代码

  • 定义了一个接口 里面定义了泛型
  • 两个实现类
//定义接口中的泛型T 在方法中使用了这个T定义参数e
interface inter1<T> {
    public void show(t e, int a);

}
//1 写一个类继承接口inter1的时候 就把泛型确定好,比如这里是String,那么show方法中的参1也就是String
class A implements inter1<Integer> {
    @Override
    public void show(t e, int a) {
        System.out.println(e + "----" + a);
    }
}
//2  B后面的E是给类定义了一个泛型
// inter1后面的E是使用了类的泛型,把它再传给接口inter1里的泛型T
// show方法是对接口的抽象方法的实现,参数里的E 和Inter1<E>这里的E保持一致
// method参数里的E只是使用了类的泛型E
class B<E> implements inter1<E> {
    @Override
    public void show(t e, int a) {
        System.out.println(e + "----" + a);
    }
    public void method(E height) {
        System.out.println(height);
    }
}

1667463493052

1.4.2. 测试方法

    public static void main(String[] args) {
        A a = new A();
        a.show(10, 20);

        B<String> b = new B<>();
        b.show("aaa", 100);
    }

1.5. 类型通配符 ?

1.5.1. 类型通配符: \<?>

  • ArrayList\<?>: 表示元素类型未知的ArrayList,它的元素可以匹配任何的类型
  • 如果使用了\<?>,ArrayList就不能添加数据了,获取出来的也是Object类型
  • 使用通配符的集合不能够修改数据了

1.5.2. 代码

  • showList方法,接收一个集合类型的数据,可以打印结合中所有数据,但不知道集合里具体类型,索引泛型写了?
  • main方法中 创建了两个不同类型的集合对象,传入测试
    public static void main(String[] args) {
        ArrayList<String> list01 = new ArrayList<>();
        list01.add("aa");
        list01.add("bb");
        list01.add("cc");

        showList(list01);

        ArrayList<Boolean> list02 = new ArrayList<>();
        list02.add(true);
        list02.add(false);
        list02.add(false);

        showList(list02);

    }

    public static void showList(ArrayList<?> list) {
        for (Object o : list) {
            System.out.println(o);
        }
    }

1.5.3. 类型通配符上限: \<? extends 类型> (源码中常见)

  • ArrayList\<? extends Number>: 它表示的类型是Number或者其子类型

1.5.4. 类型通配符下限: \<? super 类型> (用的很少)

  • ArrayList \<? super Number>: 它表示的类型是Number或者其父类型

1.5.5. 代码

    public static void main(String[] args) {
        ArrayList<Integer> list01 = new ArrayList<>();
        list01.add(11);
        list01.add(22);
        showList(list01);

        ArrayList<Double> list02 = new ArrayList<>();
        list02.add(1.5);
        list02.add(5.1);

        showList(list02);
    }

    //<? extends Number>表示只能传入 Number类型的对象 或者是子类的对象
    public static void showList(ArrayList<? extends Number> list) {
        for (Number number : list) {

        }
    }

    //传入的必须是Number类型的对象或者是Number的父类的对象  用的极少极少极少极少极少
    public static void showList1(ArrayList<? super Number> list) {
        for (Object o : list) {

        }
    }
如人饮水,冷暖自知。
最后更新于 2023-08-05