Java学习笔记——泛型

1. 泛型的定义

  • 定义类、接口、方法时,同时声明了一个或者多个类型变量(如:)称为泛型、泛型接口、泛型方法,统称为泛型
public class ArrayList<E>{
   . . .
}
  • **作用:**泛型提供了在编译阶段约束所能操作的数据类型,并自动检查的能力。这样可以避免强制类型转换,及其肯呢个出现的异常

2. 泛型类

修饰符 class 类名<类型变量, 类型变量, ...>{
   . . .
}
public class ArrayList<E>{
   . . .
}

类型变量建议用大写的英文字母,常用的有:E、T、K、V等
示例
示例代码定义了一个泛型类 MyArrayList,该类封装了一个 ArrayList 对象,并提供了 add 和 remove 方法来添加和移除元素。此外,还重写了 toString 方法,以便返回内部 ArrayList 的字符串表示形式。

  • add(E e): 将元素 e 添加到内部 ArrayList 中,并返回 true。
  • remove(E e): 从内部ArrayList 中移除元素 e,并返回 true。
  • toString(): 返回内部 ArrayList 的字符串表示形式
import java.util.ArrayList;

public class MyArrayList<E> {
     private ArrayList list=new ArrayList();
     public boolean add(E e){
         list.add(e);
         return true;
     }

     public boolean remove(E e){
         list.remove(e);
         return true;
     }

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

测试代码

public class GenericityDemo2 {
    public static void main(String[] args) {
        MyArrayList<String> mlist=new MyArrayList<>();
        mlist.add("hello");
        mlist.add("world");
        mlist.add("java");

        System.out.println(mlist);
        System.out.println(mlist.remove("hello"));
        System.out.println(mlist);

    }
}

测试结果
在这里插入图片描述

3. 泛型接口

修饰符 interface 接口名<类型变量, 类型变量, ...>{
   . . .
}
   通过一个场景来说明泛型接口:系统需要对学生数据/老师数据都要进行增删改查操作
   在这种业务场景下,如果学生和老师都单独写接口就会编写重复的接口,就可以使用泛型接口通过定义一个泛型接口,可以创建适用于多种类型的实现类,避免为多种类型编写重复的接口。此外,泛型接口使得同一个接口可以处理不同类型的数据,增加了代码的灵活性和扩展性。
   首先定义一个泛型接口
public interface Data<T> {
    void add(T t);
    void remove(T t);
    void update(T t);
    T query(int index);
}

学生类

public class Student {
    private String name;
    private int age;
    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
}

学生实现类

public class StudentData implements Data<Student>{
    private Student[] students = new Student[5];
    private int index = 0;
    private int size = 0;
    private int maxSize = students.length;



    @Override
    public void add(Student student) {
        if(index < maxSize)
        {
            students[index] = student;
            index++;
            size++;
        }
        else
        {
            System.out.println("数组已满,无法添加");
        }

    }

    @Override
    public void remove(Student student) {
        for(int i = 0; i < size; i++)
        {
            if(students[i].equals(student))
            {
                students[i] = students[i+1];
                size--;
            }
        }

    }

    @Override
    public void update(Student student) {
        for(int i = 0; i < size; i++)
        {
            if(students[i].equals(student))
            {
                students[i] = student;
            }
        }

    }
    @Override
    public Student query(int index) {
        if(index < size)
        {
            return students[index];
        }
        return null;
    }
}

教师类

public class Teacher {
    private String name;
    private int age;
    public Teacher(String name, int age)
    {
        this.name = name;
        this.age = age;
    }
    public String getName()
    {
        return name;
    }
    public void setName(String name)
    {
        this.name = name;
    }
    public int getAge()
    {
        return age;
    }
    public void setAge(int age)
    {
        this.age = age;
    }
}

教师实现类

public class TeacherData implements Data<Teacher>{
    private Teacher[] teachers=new Teacher[5];
    private int index;
    private int size;
    private int maxSize = teachers.length;

    @Override
    public void add(Teacher teacher) {
        if(index < maxSize)
        {
            teachers[index] = teacher;
            index++;
            size++;
        }
        else
        {
            System.out.println("数组已满,无法添加");
        }


    }

    @Override
    public void remove(Teacher teacher) {
        for(int i = 0; i < size; i++)
        {
            if(teachers[i].equals(teacher))
            {
                teachers[i] = teachers[i+1];
                size--;
            }
        }

    }

    @Override
    public void update(Teacher teacher) {
        for(int i = 0; i < size; i++)
        {
            if(teachers[i].equals(teacher))
            {
                teachers[i] = teacher;
            }
        }

    }

    @Override
    public Teacher query(int index) {
        if(index < size)
        {
            return teachers[index];
        }
        return null;
    }
}

测试代码

public class GenericDemo3 {
    public static void main(String[] args)
    {
        //测试学生接口
        System.out.println("----------学生信息----------");
        StudentData studentData=new StudentData();
        studentData.add(new Student("张三",20));
        studentData.add(new Student("李四",21));
        studentData.add(new Student("王五",22));
        studentData.remove(new Student("王五",22));
        studentData.update(new Student("李四",32));

        System.out.println(studentData.query(1));
        System.out.println(studentData.query(2));

        //测试老师接口
        System.out.println("----------老师信息----------");
        TeacherData teacherData=new TeacherData();
        teacherData.add(new Teacher("张八",30));
        teacherData.add(new Teacher("李九",31));
        teacherData.add(new Teacher("王十",32));
        teacherData.remove(new Teacher("王十",32));
        teacherData.update(new Teacher("李九",22));
        System.out.println(teacherData.query(1));
        System.out.println(teacherData.query(2));
    }
}

运行结果
在这里插入图片描述

4. 泛型方法

修饰符 <类型变量, 类型变量, ...> 返回值类型 方法名(x形参列表){

通过来两个泛型方法示例进行理解
```java
public static <T> void printArray(T[] names){
       for (T name : names) {
           System.out.println(name);
       }
}

printArray方法接收一个泛型数组 T[] names,其中 T 可以是任何对象类型。该方法可以接受任何类型的数组(如 String[]、Integer[]等)。

    public static <T> T getMax(T[] names){
        return null;
    }

同样接收一个泛型数组 T[] names,返回值也是一个泛型。这样就可以接收任何类型的参数以及返回任何类型的结果

5. 通配符和泛型的上下限

通配符

就是“?”,可以在“使用泛型”的时候代表一切类型;
E、T、K、V是在定义泛型的时候使用
在一个场景下理解:如果多个品牌的车要进行比赛
首先定义了一个父类Car,三个子类车的品牌“BYD”、“XIAOMI”、“WL”,然后还要定义一个go方法是实际的比赛

import java.util.ArrayList;

public class GenericDemo5 {
    public static void main(String[] args) {
        ArrayList<XIAOMI> xiaomis= new ArrayList<>();
        xiaomis.add(new XIAOMI());
        xiaomis.add(new XIAOMI());
        xiaomis.add(new XIAOMI());
        xiaomis.add(new XIAOMI());
        go(xiaomis);
    }
    public static void go(ArrayList<XIAOMI> cars){

    }
}

如果只有XIAOMI进行比赛是没有问题的,但一旦其它车品牌要用到go方法就会报错
在这里插入图片描述
因此这里可以用到通配符,使得go方法可以复用
在这里插入图片描述
然而,这种方法就会导致对于传入的类型没有限制,如果传入一个动物猫也是可以的,如图:
在这里插入图片描述
因此就需要用到泛型的上下限

泛型的上下限

  • 泛型的上限: ?extends Car: 表示?能接收的必须是Car或者其子类
  • 泛型的下限: ?super Car: 表示?能接收的必须是Car或者其父类
    在这里插入图片描述
    在代码中加了上下限,由于Cat不是Car的子类,所以不能作为参数传入

6. 泛型支持的类型

  • 泛型不支持基本数据类型,只能支持对象类型(引用数据类型)
  • 泛型擦除:泛型在编译的时候会被擦除,只保留类型,不保留泛型信息,最后都会变成一个Object
    因此引出了包装类

7.包装类

就是把基本数据类型的数据包装成对象的类型

基本数据类型对应的包装类(引用数据类型)
byteByte
shortShort
intInteger
longLong
charCharacter
floatFloat
doubleDouble
booleanBoolean

7.1 手动包装

		Integer i1 = Integer.valueOf(10);
        Integer i2 = Integer.valueOf(20);
        System.out.println(i1 ==i2);

在这里插入图片描述

7.2 自动装箱

基本数据类型自动转换为对象类型,不需要额外的包装

        Integer i3 = 10;//相当于Integer i1 = Integer.valueOf(10);
        Integer i4 = 10;
        System.out.println(i3 == i4);

在这里插入图片描述

7.3 自动拆箱

对象类型转换为基本数据类型,不需要额外的拆箱

        int i5 = i3;
        System.out.println(i5);

在这里插入图片描述

7.4 包装类具备的其他功能

  • 可以把基本类型的数据转换成字符串类型
    在这里插入图片描述

  • 可以把字符串类型的数值转换成数值本身对应的真实数据类型
    在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值