Bootstrap

【JAVA基础】泛型

前言

        在学习泛型前,我们得明白为什么要学习这个!!!,在JAVA SE 5.0前,ArrayList类只维护一个Object数组,使得在后面获取元素时,需要我们自己将Object对象强制类型转换 。这时候就很容易引起ClassCastException异常。因此在JAVA SE 5.0 引进了泛型,可以在编译时检查非法数据类型。

1、泛型的概念

        泛型允许你在定义类、接口和方法时使用类型参数。这些类型参数在实际使用时会被具体的类型所替换,从而使得同一个代码可以被很多不同类型的对象所重用。

2、泛型体系

2.1 泛型类

2.1.1 泛型类语法

常用泛型标识:T、E、K、V

class 类名称 <泛型标识,泛型标识...>{
    private 泛型标识 变量名;
}
public class Common <T>{
    private T value;

    public Common(T value) {
        this.value = value;
    }

    public Common() {
    }

    public T getValue() {
        return value;
    }

    public void setValue(T value) {
        this.value = value;
    }

    @Override
    public String toString() {
        return "Common{" +
                "value=" + value +
                '}';
    }
}
public class Client {

    public static void main(String[] args) {
        //泛型类在创建对象的时候指定操作的具体数据类型(泛型类不支持基本数据类型)
        Common<Integer> commonInteger = new Common<>(2);
        //输出 Common{value=2}
        System.out.println(commonInteger);
        Common<String> commonString = new Common<>("A");
        //输出 Common{value=A}
        System.out.println(commonString);
    }
}

注意点:

(1)泛型类在创建对象的时候指定需要操作的数据类型。

(2)未指名具体的操作类型,则默认为Object类型。泛型不支持基本数据类型。

(3)泛型本质上都是类类型

(4)子类(泛型类)继承父类(泛型类),子类与父类泛型需要一致。

(5)子类(非泛型类)继承父类(泛型类),父类需要指明具体类型。

2.2 泛型接口

2.2.1 泛型接口语法

interface 接口名<泛型标识,泛型标识...> {
    泛型标识 方法名();
}

2.2.1 用法

(1)定义一个泛型接口

public interface Generics<T> {
    T getValue();
}

(2) 定义一个类去实现泛型接口

实现类不是泛型类。需要去明确泛型接口数据类型。如果不指明泛型接口的具体类型是什么,那么方法默认为Object类型。

实现类是泛型类。实现类与接口类型一致

public class GenericsImpl implements Generics{
    @Override
    public Object getValue() {
        return null;
    }
}

2.3 泛型方法

2.3.1 泛型方法语法

只有申明了<T>的方法才是泛型方法,在泛型类中使用泛型成员方法不是泛型方法。

修饰符 <T,E...> 返回值 方法名称(形参列表){

    方法体...
}
public class GenericMethodExample {

    // 定义一个泛型方法
    public static <T> void printArray(T[] array) {
        for (T element : array) {
            System.out.println(element);
        }
    }

    public static void main(String[] args) {
        // 使用泛型方法
        Integer[] intArray = {1, 2, 3, 4, 5};
        String[] stringArray = {"Hello", "World"};

        printArray(intArray);   
        printArray(stringArray); 
    }
}

2.4 类型通配符

2.4.1 类型通配符的定义

类型通配符一般是使用“?”代替具体类型实参。使用上面已经定义好的泛型类Common来举例。

public class Client {
    public static void main(String[] args) {
        Common<Number> value1 = new Common<>();
        value1.setValue(100);
        getValue(value1);

        Common<Integer> value2 = new Common<>();
        value1.setValue(200);
        getValue(value2);
    }
    public static void getValue(Common<Number> common){
        Number value = common.getValue();
        System.out.println(value);
    }
}

目前这段代码报了一个错(需要Number类型,但是我们传递了一个Integer类型),明明Integer是Number子类却报错了,我们不能已多态的思想去看待泛型。那我们要怎么解决这个问题?重新复制粘贴一个方法,nonono,这里就可以使用上类型通配符,代表着一个不确定的类型。

2.4.2 类型通配符的上限

类/接口<? extends 实参类型>

要求泛型类型,是实参类型/实参类型的子类。

2.4.3 类型通配符的上限

类/接口<? super 实参类型>

要求泛型类型,是实参类型/实参类型的父类。

;