泛型类

使用时需通过<具体类型>指定泛型参数的实际类型(不支持基本数据类型,需用包装类,如intInteger

泛型类的类型参数在编译时会被 “类型擦除”:编译器将泛型参数替换为Object(或上限类型),因此运行时不存在 “泛型类型”(如GenericClass<String>GenericClass<Integer>在运行时是同一个类)。

不能在静态成员中使用泛型类的类型参数(静态成员属于类,初始化时泛型类型未确定)。

public class GenericClass<T> {
    // 错误:静态成员不能使用泛型类的T
    // private static T staticData;
}

泛型方法

泛型方法是在方法定义时声明 “类型参数”,与类是否是泛型类无关。

// 语法:[访问修饰符] <类型参数1, 类型参数2, ...> 返回值类型 方法名(参数列表) { ... }
// 关键:类型参数声明(<T>)必须在返回值类型之前
public class GenericMethodDemo {
    // 泛型方法:打印任意类型的数组
    public <T> void printArray(T[] array) {
        for (T element : array) {
            System.out.print(element + " ");
        }
        System.out.println();
    }

    // 泛型方法:返回两个元素中的较大值(需限制T为Comparable子类)
    public <T extends Comparable<T>> T getMax(T a, T b) {
        return a.compareTo(b) >= 0 ? a : b;
    }
}

泛型接口

实现泛型接口的两种方式

方式 1:实现接口时指定具体类型

// 实现GenericInterface,指定T为String类型
public class StringProcessor implements GenericInterface<String> {
    private String result;

    @Override
    public void process(String data) {
        // 处理String类型数据(如转为大写)
        result = data.toUpperCase();
    }

    @Override
    public String getResult() {
        return result;
    }
}

// 使用
StringProcessor processor = new StringProcessor();
processor.process("hello");
System.out.println(processor.getResult()); // 输出:HELLO

方式 2:实现接口时保留泛型(成为 “泛型实现类”)

// 实现GenericInterface,保留T作为泛型参数
public class GenericProcessor<T> implements GenericInterface<T> {
    private T result;

    @Override
    public void process(T data) {
        // 通用处理逻辑(如直接保存数据)
        this.result = data;
    }

    @Override
    public T getResult() {
        return result;
    }
}

// 使用时指定具体类型
GenericProcessor<Integer> intProcessor = new GenericProcessor<>();
intProcessor.process(100);
System.out.println(intProcessor.getResult()); // 输出:100

GenericProcessor<Double> doubleProcessor = new GenericProcessor<>();
doubleProcessor.process(3.14);
System.out.println(doubleProcessor.getResult()); // 输出:3.14

泛型支持通过extendssuper限制类型参数的范围,避免传入不合法的类型。

public class NumberBox<T extends Number> {
}

public <T super Integer> void addIntegerToCollection(T element, Collection<T> collection) {
    collection.add(element);
}

泛型通配符的三种形式

(1)无界通配符(?

表示 “未知的任意类型”,适用于 “只读取集合元素,不添加元素” 的场景(因为无法确定元素类型,添加任何类型都可能不安全)。

// 定义接收“任意泛型List”的方法(无界通配符)
public void printList(List<?> list) {
    for (Object obj : list) { // 只能用Object接收元素(未知类型)
        System.out.print(obj + " ");
    }
    System.out.println();
}

// 使用:可传入任意泛型的List
List<String> strList = Arrays.asList("a", "b", "c");
List<Integer> intList = Arrays.asList(1, 2, 3);
List<Double> doubleList = Arrays.asList(1.1, 2.2);

printList(strList);   // 输出:a b c 
printList(intList);   // 输出:1 2 3 
printList(doubleList); // 输出:1.1 2.2 

// 注意:无界通配符的List不能添加元素(除了null)
List<?> unknownList = new ArrayList<String>();
unknownList.add(null); // 允许(null是所有类型的默认值)
// unknownList.add("hello"); // 错误:无法确定类型,添加不安全

(2)上限通配符(? extends 父类型

表示 “未知类型,但必须是父类型的子类或父类型本身”,适用于 “只读取元素,不添加元素” 的场景(与无界通配符类似,但能限制元素的上限类型,支持调用父类型方法)。

// 定义接收“泛型为Number子类的List”的方法(上限通配符)
public double sumList(List<? extends Number> list) {
    double sum = 0.0;
    for (Number num : list) { // 可用Number接收元素(上限类型)
        sum += num.doubleValue(); // 调用Number的方法(安全)
    }
    return sum;
}

// 使用:可传入List<Integer>、List<Double>等(都是Number的子类)
List<Integer> intList = Arrays.asList(10, 20, 30);
List<Double> doubleList = Arrays.asList(1.5, 2.5);
List<Number> numberList = Arrays.asList(5, 10.5);

System.out.println(sumList(intList));    // 输出:60.0
System.out.println(sumList(doubleList)); // 输出:4.0
System.out.println(sumList(numberList)); // 输出:15.5

// 注意:上限通配符的List也不能添加元素(除了null)
List<? extends Number> numList = new ArrayList<Integer>();
// numList.add(10); // 错误:无法确定numList的具体类型(可能是List<Double>)

(3)下限通配符(? super 子类型

表示 “未知类型,但必须是子类型的父类型或子类型本身”,适用于 “只添加元素,不读取元素” 的场景(能确定添加的元素类型是子类型,父类型集合可安全接收)。

// 定义向“泛型为Integer父类型的List”添加元素的方法(下限通配符)
public void addIntegers(List<? super Integer> list) {
    list.add(10); // 允许添加Integer(子类型)
    list.add(20);
    list.add(new Integer(30));
}

// 使用:可传入List<Integer>、List<Number>、List<Object>(都是Integer的父类型)
List<Integer> intList = new ArrayList<>();
List<Number> numberList = new ArrayList<>();
List<Object> objList = new ArrayList<>();

addIntegers(intList);    // intList变为[10,20,30]
addIntegers(numberList); // numberList变为[10,20,30]
addIntegers(objList);    // objList变为[10,20,30]

// 注意:下限通配符的List读取元素时,只能用Object接收(未知父类型的具体类型)
for (Object obj : numberList) {
    System.out.print(obj + " "); // 输出:10 20 30 
}
分类: Java-Backend 标签: Java

评论

暂无评论数据

暂无评论数据

目录