7-自定义泛型

自定义泛型结构

泛型类的定义和实例化

  • 泛型------>添加限制
/*
Demo01就是一个普通的类
Demo01<E>就是一个泛型类
<>里面就是一个参数类型,但是这个类型是什么呢?这个类型现在是不确定的,相当于一个占位
但是现在确定的是这个类型一定是一个引用数据类型
 */
public class Demo01<E> {
    //属性
    int age;
    String name;
    E sex;//E类型的sex-----<E>中类型确定,则E sex类型确定

    //方法
    public void a(E n){

    }
    public void b(E[] m){

    }
}

class Test{
    public static void main(String[] args) {
        //在实例化Demo01时--->才会决定E的类型
        //Demo01实例化
        //1.实例化的时候不指定泛型:默认泛型为Object类型
        Demo01 gt1 = new Demo01();//相当于<Object>
        gt1.a("abc");//调用a方法
        gt1.a(17);
        gt1.a(9.8);
        gt1.b(new String[]{"a","b","c"});//调用b方法,需要传入Object类型数组

        //2.实例化时指定泛型
        Demo01<String> gt2 = new Demo01<>();
        gt2.sex = "男"; //sex属性变成String类型
        gt2.a("abc");//只能传入String类型
        gt2.b(new String[]{"a","b","c"});
    }

继承情况

1.父类指定泛型

class SubDemo01 extends Demo01<Integer>{//SubDemo01继承Demo01--->其中父类指定了泛型

}
class Test{
    public static void main(String[] args) {

        //指定父类泛型,那么子类就不需要再指定泛型了,可以直接使用
        SubDemo01 sgt = new SubDemo01();
        sgt.a(19);//只能传Integer
    }
}

2.父类不指定泛型

  • 若父类不指定泛型,那么子类也会变成一个泛型类,那这个E的类型可以在创建子类对象的时候确定
class SubDemo01_2<E> extends Demo01<E>{
    //SubDemo01_2继承Demo01--->其中父类未指定泛型
}
class Test{
    public static void main(String[] args) {

        //创建子类对象确定泛型
        SubDemo01_2<String> s = new SubDemo01_2<>();
        s.a("abc");//只能传入String类型
    }

应用场合

  • ArrayList实现就是运用泛型类,看懂API
  • 泛型接口跟泛型类一样

细节

  • 泛型类可以定义多个参数类型
//可以是多个参数类型
public class Demo02<A,B,C> {
    A age;
    B name;
    C sex;

    public void a(A m,B n, C x){
        
    }
}
  • 泛型类的构造器的写法

public class Demo02<A,B,C> {

​ public Demo02<A,B,C>(){
​ //构造器中不许加泛型
​ }
}

  • 不同的泛型的引用类型不可以相互赋值

ArrayList list1 = null;
ArrayList list2 = null;
list1 = list2;

  • 泛型如果不指定,那么就会被擦除,泛型对应的类型为Object类型
  • 泛型类中的静态方法不能使用类的泛型:

public static int c(A a){
//静态方法是在类加载时存在--->优先于对象存在,但是创建对象时A的类型才被确定,故不能用静态方法
return 10;
}

  • 不能直接使用E[]的创建:

public void a(A m,B n, C x){
A[] = new A[10];
}

泛型方法

  1. 什么是泛型方法
    • 这个方法的泛型的参数类型要和当前的类的泛型无关
public class Demo03<E> {
    public void a(E e){
        //这个不是泛型方法
    }
    public <T> void b(T t){
        //参数类型T 跟泛型类中的E 不同--->泛型方法
    }
}
  1. 泛型方法定义的时候,前面要加上

    • 原因:如果不加的话,会把T当作一种数据类型,然而代码中没有T类型那么就会报错
  2. 调用方法

    • T的类型是在调用方法的时候确定的
    public static void main(String[] args) {
        Demo03<String> tg = new Demo03<>();
        tg.b("abc");//T的类型在调用方法时才最终确定,故可以传任意类型
        tg.b(19);
        tg.b(true);
    }
  1. 泛型方法可否是静态方法
    • 可以是静态方法(静态方法优先于对象加载,没有对象是时静态方法随着类一起加载)
    • T的确定是随着方法的调用而确定,故可以是静态
public class Demo03<E> {
    public /*static*/ void a(E e){
        //这个不是泛型方法
        //不能是静态方法,E是随着对象确定才确定
    }
    public static <T> void b(T t){
        //参数类型T 跟泛型类中的E 不同--->泛型方法
        //T的类型是在调用方法时确定--->可以是静态
    }
}

泛型参数存在继承关系情况

    public static void main(String[] args) {
        Object obj = new Object();
        String s = new String();
        //String与Object有继承关系。(所有的类都直接或间接继承Object)
        obj = s ;//父类引用指向子类对象(多态一种形式)

        //两个数组之间存在数组关系吗
        Object[] objArr = new Object[10];
        String[] strArr = new String[10];
        objArr = strArr;//也可以,多态一种形式

        //对应泛型之间存在继承关系
        List<Object> list1 = new ArrayList<>();
        List<String> list2 = new ArrayList<>();
        list1 = list2;//报错,不存在父类子类关系
        //为什么?
        //ArrayList--->集合里都是Object类型
        /*list2中指定泛型String只是一个标签,
        本质集合都是Object类型的,
        限制只能String类型数据存入,
        实质也是将String类型数据放父Object类型的集合中
        故list1与list2底层本质是一样的(Object类型数组)
        list2指定String泛型只是在编译器,即写代码时进行限制
        所有list1与list2没有继承关系,
        是并列关系
         */
    }

通配符

1.在没有通配符的时候:

  • 下面的a方法,相当于方法的重复定义,报错
/*    public void a(List<Object> list){
    }
    public void a(List<String> list) {//想传String类型--->重载
    }
    public void a(List<Integer> list) {//想传Integer类型--->重载
    }
    报错
    泛型是对编译时进行的限制--->标签作
    故这几个重载参数本质都是Object-->重复定义
    --->通配符解决
    */

2.引入通配符:

        //这些泛型接口都是并列关系,没有继承关系
        List<Object> list1 = new ArrayList<>();
        List<String> list2 = new ArrayList<>();
        List<Integer> list3 = new ArrayList<>();

        //通配符:?
        List<?> list = null;
        list = list1;
        list = list2;
        list = list3;

3.使用通配符后改1中的a方法:

public class Demo05 {
/*    public void a(List<Object> list){
    }
    public void a(List<String> list) {//想传String类型--->重载
    }
    public void a(List<Integer> list) {//想传Integer类型--->重载
    }
    报错
    泛型是对编译时进行的限制--->标签作
    故这几个重载参数本质都是Object-->重复定义
    --->通配符解决
    */
    public void a(List<?> list){
        //内部遍历的时候永Object即可,不用?
        for (Object a : list) {
            System.out.println(a);
        }
    }

}
class Test3{
    public static void main(String[] args) {
        Demo05 demo05 = new Demo05();
        //其任何子类都可以传进去
        demo05.a(new ArrayList<Integer>());
        demo05.a(new ArrayList<String>());
        demo05.a(new ArrayList<Object>());//Object也属于?的子类
    }
}
  • 查看API中应用位置

通配符使用细节

  1. 通配符泛型,在内部操作时,用Object接收,而不用?
  2. 集合的写入操作
  3. 集合的读取操作
        //1.遍历:内部遍历的时候用Object即可,不用?
        for (Object a : list) {
            System.out.println(a);
        }

        //2.数据的写入操作:
        //传入list肯定是接到一个具体的集合
        //list.add("abc");--->出错,不能随意添加数据,因为在main函数传入数据指定了泛型
        list.add(null);//只能填null,但是也没有实际意义

        //3.数据的读取操作:
        Object s = list.get(0);//读取可以用Object类型接收

泛型受限

public class Person {//Person继承与Object
}
public class Student extends Person{
}
        //a,b,c集合中只是泛型存在子类父类关系,但这几个集合直接不存在子类父类关系(并列)
        List<Object> a = new ArrayList<>();
        List<Person> b = new ArrayList<>();
        List<Student> c = new ArrayList<>();
        /*
        1.开始使用泛型受限:泛型的上限
        List<? extends Person>:
        就相当于:
        List<? extends Person>是List<Person>的父类,是List<Person的子类>的父类
        (另注:之前的单独通配符List<?>实际上是List<? extends Object>)
         */
        List<? extends Person> list1 = null;
        //list1 = a;--->报错  a是Object类型,是Person的父类,超过泛型上限
        list1 = b;
        list1 = c;

        /*
        2.开始使用泛型受限:泛型的下限
        List<? super Person>:
        就相当于:
        List<? super Person>是List<Person>的父类。是List<Person的父类>的父类
         */
        List<? super Person> list2 = null;
        list2 = a;
        list2 = b;
        //list2 = c;--->报错   c是Student类型,是Person子类,超过泛型下限
posted @ 2024-08-19 17:47  呆头尖瓜  阅读(2)  评论(0编辑  收藏  举报