泛型

泛型

泛型是JDK5引入的特性,可以在编译阶段约束操作的数据类型,并进行检查。

泛型格式:<数据类型>

注意:泛型只能用引用数据类型

如果不加泛型,那么在添加数据的时候会默认为是Object类,但是多态的弊端是不能访问子类的特有功能,而且进行强转的话也会出问题,如果有一个是Integer,你要强转成String类型,肯定会报错。

泛型的好处:

  • 统一数据类型
  • 把运行期间的问题提前到了编译期间,避免强制类型转换可能出现的异常,因为在编译阶段类型就确定下来了。

扩展知识:泛型在Java中是伪泛型,只在编译阶段有效。编译为class字节码文件的时候,泛型就消失,这种现象叫做泛型的擦除。

泛型的细节:

  • 泛型中不能写基本数据类型。
  • 指定泛型的具体类型后,传递数据时,可以传入该类类型或者其子类类型。
  • 如果不写泛型,类型默认是Object

泛型可以在很多地方进行定义。

使用场景:当一个类中,某个变量的数据类型不确定时,就可以定义带有泛型的类。

泛型类

自己重写ArrayList

public class MyArrayList<E> {

    Object[] obj = new Object[10];
    int size;

    public boolean add(E e){
        obj[size] = e;
        size++;
        return true;
    }


    public E getIndex(int index) {
        return (E) obj[index];
    }

    @Override
    public String toString() {
        return Arrays.toString(obj);
    }
}

泛型方法

方法中形参类型不确定时

  • 可以使用类名后面定义的泛型

  • 在方法上申明定义自己的泛型

    public class MyArrayList{
     
      public <E> boolean add(E e){
              obj[size] = e;
              size++;
              return true;
          }
    }
    

案例:

定义一个工具类ListUtil,类中定义一个静态方法addAll,用来添加多个集合的元素

public class ListUtil {

    private ListUtil(){

    }

    /**
     * 参数一:集合
     * 参数二 ~ 最后 要添加的数据
     */
    public static <E> void addAll(ArrayList<E> list,E e1,E e2,E e3,E e4){
        list.add(e1);
        list.add(e2);
        list.add(e3);
        list.add(e4);
    }

    public static <E> void addAll(ArrayList<E> list,E...e){
        for (E element : e) {
            list.add(element);
        }
    }
}

泛型接口

public interface 接口名<E>{
    
}

重点:如何使用泛型接口?

  • 实现类给出具体类型

    public class MyArrayList2 implements List<String>{
        
    }
    
  • 实现类延续泛型,创建对象时再确定。

    public class MyArrayList2 implements List<E>{
        
    }
    
    //创建该对象
    MyArrayList2<String> list = new MyArrayList2<>();
    

泛型的继承和通配符

  • 泛型不具备继承性,但是数据具有继承性。

    定义几个类,父类 Ye 子类Fu 子类Zi

 public static void method(ArrayList<Ye> list){
        
 }

main方法{
    ArrayList<Ye> list1 = new ArrayList<>();
    ArrayList<Fu> list2 = new ArrayList<>();
    ArrayList<Zi> list3 = new ArrayList<>();
    method(list1);
    method(list2);  //报错
    method(list3);  //报错   method方法指定泛型类型为Ye,泛型不能继承,所以子类使用会报错
}

泛型方法里面写什么类型,传递的就只能是什么类型的数据,

弊端:

​ 它可以接收任意数据类型

我希望:本方法虽然不确定类型,但是我只希望只能传递Ye Fu Zi

此时我们就可以使用泛型的通配符:

​ ?也表示不确定的类型

​ 但是它可以进行类型限定

​ ? extends E :表示可以传递E或者E所有的子类类型

​ ? super E :表示可以传递E 或者 E 所有的父类类型。

应用场景:

1.如果我们在定义类、方法、接口的时候,如果类型不确定,就可以定义泛型类、泛型方法、泛型接口。

2.如果类型不确定,但是能知道以后只能传递某个继承体系中的,就可以泛型的通配符

泛型的通配符:
关键点:可以限定类型的范围。

综合练习

需求:

​ 定义一个继承结构:

​ 动物

​ 丨 丨

​ 猫 狗

​ 丨 丨 丨 丨

​ 波斯猫 狸花猫 泰迪 哈士奇

属性:名字、年龄

行为:吃东西

​ 方法体打印:一只叫XXX的,X岁的波斯猫,正在吃小饼干

​ 方法体打印:一只叫XXX的,X岁的狸花猫,正在吃鱼

​ 方法体打印:一只叫XXX的,X岁的泰迪,正在吃骨头,边吃边蹭

​ 方法体打印:一只叫XXX的,X岁的哈士奇,正在吃骨头,边吃边拆家

测试类中定义一个方法,用于饲养动物:

public static void keepPet(ArrayList<???> list){
	//遍历集合,调用动物的eat方法
}

要求1:该方法能养所有品种的猫,但不能养狗。

要求2:该方法能养所有品种的狗,但不能养猫。

要求3:该方法能养所有品种的猫,但不能养狗。

在测试类前,根据继承结构创建各个对象,各结点类型为抽象类,叶子结点实现自己的父类并且进行方法重写即可

public class Test {
    public static void main(String[] args) {
        ArrayList<PersianCat> list1 = new ArrayList<>();
        ArrayList<LiHuaCat> list2 = new ArrayList<>();

        ArrayList<TeddyDog> list3 = new ArrayList<>();
        ArrayList<HuskyDog> list4 = new ArrayList<>();

        list1.add(new PersianCat("aaa",3));
        list2.add(new LiHuaCat("bbb",3));
        keepCat(list1);
        keepCat(list2);

        list3.add(new TeddyDog("ccc",3));
        list4.add(new HuskyDog("ddd",3));
        keepDog(list3);
        keepDog(list4);


    }

    public static void keepCat(ArrayList<? extends Cat> list){
        for (int i = 0; i < list.size(); i++) {
            Cat cat = list.get(i);
            cat.eat();
        }
    }

    public static void keepDog(ArrayList<? extends Dog> list){
        for (int i = 0; i < list.size(); i++) {
            Dog dog = list.get(i);
            dog.eat();
        }
    }

    public static void keepAnimal(ArrayList<? extends Animal> list){
        for (int i = 0; i < list.size(); i++) {
            Animal animal = list.get(i);
            animal.eat();
        }
    }
}

posted @ 2023-03-19 14:59  戒爱学Java  阅读(36)  评论(0编辑  收藏  举报