Java泛型
Java泛型

Java泛型

Java 泛型(generics)是 JDK 5 中引入的一个新特性, 泛型提供了编译时类型安全检测机制,该机制允许程序员在编译时检测到非法的类型。泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数。

泛型的好处:统一数据类型,将运行期的错误提升到编译期

注意事项:泛型中只能编写引用数据类型,如Integer、Double等,使用int、double会报错

java 中泛型标记符:

  • E – Element (在集合中使用,因为集合中存放的是元素)
  • T – Type(Java 类)
  • K – Key(键)
  • V – Value(值)
  • N – Number(数值类型)
  •  – 表示不确定的 java 类型

泛型类

泛型类的声明和非泛型类的声明类似,除了在类名后面添加了类型参数声明部分。

class Student<E> {
    private E e;

    public E getE() {
        return e;
    }

    public void setE(E e) {
        this.e = e;
    }
}

创建不同类型的对象,会创建不同数据类型的成员变量 e 。

泛型方法

下面是定义泛型方法的规则:

  • 所有泛型方法声明都有一个类型参数声明部分(由尖括号分隔),该类型参数声明部分在方法返回类型之前(在下面例子中的 <E>)。
  • 每一个类型参数声明部分包含一个或多个类型参数,参数间用逗号隔开。一个泛型参数,也被称为一个类型变量,是用于指定一个泛型类型名称的标识符。
  • 类型参数能被用来声明返回值类型,并且能作为泛型方法得到的实际参数类型的占位符。

泛型方法也分为静态方法和非静态方法。

非静态泛型方法

非静态的方法 : 内部的泛型, 会根据类的泛型去匹配。

如上文中的 setE() 方法:

public void setE(E e) {
        this.e = e;
    }

静态泛型方法

静态的方法 : 静态方法中如果加入了泛型, 必须声明出自己独立的泛型。在调用方法, 传入实际参数的时候, 确定到具体的类型。

public static<T> void printArray(T[] arrays){
        for (T t : arrays){
            System.out.println(t);
        }
    }
public static void main(String[] args) {
        String[] arr1 = {"a", "b", "c"};
        Integer[] arr2 = {1, 2, 3};
        Double[] arr3 = {1.1, 2.2, 3.3};

        printArray(arr1);
        printArray(arr2);
        printArray(arr3);
    }

运行结果:

泛型接口

类实现接口的时候,如果接口带有泛型,有两种操作方法

  • 实现类:实现接口的时候确定到具体的类型
  • 类延续接口的泛型:没有指定具体类型, 就让接口的泛型, 跟着类的泛型去匹配

实现类

给出一个泛型接口,其中有一个show方法:

interface Inter<E> {
    void show(E e);
}

对于实现类,在实现接口的时候就要确定具体的数据类型

class InterAImpl implements Inter<String> {

    @Override
    public void show(String s) {
      
    }
}

类延续接口的泛型

没有指定具体类型, 就让接口的泛型, 跟着类的泛型去匹配。

类延续了接口的泛型:

class InterBImpl<E> implements Inter<E>{

    @Override
    public void show(E e) {

    }
}

在创建对象的时候再确定具体的数据类型

InterBImpl<String> i = new InterBImpl<>();

泛型通配符

  • ?(任意类型)
  • ? extends E(只能接收 E 或是 E 的子类)
  • ? super E(只能接收 E 或是 E 的父类)

给出抽象父类和两个子类:

abstract class Employee {
    private String name;
    private double salary;

    public Employee() {
    }

    public Employee(String name, double salary) {
        this.name = name;
        this.salary = salary;
    }

    public abstract void work();

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public double getSalary() {
        return salary;
    }

    public void setSalary(double salary) {
        this.salary = salary;
    }

    public String toString() {
        return "Employee{name = " + name + ", salary = " + salary + "}";
    }
}

class Coder extends Employee {
    @Override
    public void work() {
        System.out.println("程序员写代码...");
    }
}

class Manager extends Employee {
    @Override
    public void work() {
        System.out.println("项目经理分配任务...");
    }
}

创建含有泛型通配符的静态方法:

public static void method(ArrayList<?> list){
        for (Object o : list) {
            Employee e = (Employee) o;
            e.work();
        }
    }

在主函数中创建对象并调用method方法

public static void main(String[] args) {

        ArrayList<Coder> list1 = new ArrayList<>();
        list1.add(new Coder());

        ArrayList<Manager> list2 = new ArrayList<>();
        list2.add(new Manager());

        method(list1);
        method(list2);
}

再创建一个String类型的对象,并调用method方法。由于list3不是类对象,会发生报错

public static void main(String[] args) {

        ArrayList<Coder> list1 = new ArrayList<>();
        list1.add(new Coder());

        ArrayList<Manager> list2 = new ArrayList<>();
        list2.add(new Manager());


        ArrayList<String> list3 = new ArrayList<>();
        list3.add("abc");

        method(list1);
        method(list2);
        method(list3);
}

修改method方法,使用 ?extends E 通配符,会发现method传入list3参数,编译报错:

public static void method(ArrayList<? extends Employee> list){
        for (Object o : list) {
            Employee e = (Employee) o;
            e.work();
        }

再创建一个Object类型的对象,并调用method方法。由于list4不是Employee的子类对象,编译报错

修改method方法,使用 ?super E 通配符,调用method方法传入list4参数,正常运行:

public static void method(ArrayList<? super Employee> list){
        for (Object o : list) {
            Employee e = (Employee) o;
            e.work();
        }

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

index