授课语音

Java 泛型

本课内容涵盖泛型的概念、定义泛型类、泛型接口、泛型方法、通配符、上下限、支持的类型、包装类和最佳实践等内容,附带详细的代码示例和中文注释,帮助您深入理解泛型的用法及应用场景


1. 认识泛型

介绍

泛型是一种参数化类型的机制,允许类、接口和方法在编写时不指定具体的数据类型,而在使用时通过传入实际类型进行实例化。泛型可以提高代码的复用性和安全性,并减少类型转换的错误。

作用

使用泛型的主要目的是提高类型安全性,避免在运行时因类型转换错误导致的 ClassCastException。泛型的类型检查是在编译阶段进行的,可以有效避免代码在运行时出现类型不匹配的问题。


2. 自定义泛型类

介绍

Java 支持在定义类时使用泛型参数。定义泛型类时,通常使用 <T> 表示类型参数 T,这个 T 可以在类中表示任意类型,实例化时再传入实际的类型。

代码示例

// 定义一个泛型类 Box,T 是类型参数
public class Box<T> {
    private T item; // 泛型属性,类型为 T

    // 构造方法
    public Box(T item) {
        this.item = item;
    }

    // 获取 item 值
    public T getItem() {
        return item;
    }

    // 设置 item 值
    public void setItem(T item) {
        this.item = item;
    }

    // 打印 item 信息
    public void printInfo() {
        System.out.println("Item: " + item);
    }
}

// 测试自定义泛型类 Box 的使用
public class Main {
    public static void main(String[] args) {
        // 创建一个 Integer 类型的 Box
        Box<Integer> integerBox = new Box<>(123);
        integerBox.printInfo(); // 输出:Item: 123

        // 创建一个 String 类型的 Box
        Box<String> stringBox = new Box<>("Hello");
        stringBox.printInfo(); // 输出:Item: Hello
    }
}

3. 泛型接口

介绍

Java 支持接口使用泛型参数。通过定义泛型接口,可以让实现类根据需求指定类型,从而实现更加通用的接口设计。

代码示例

// 定义泛型接口 Container,类型参数为 T
public interface Container<T> {
    void add(T item);     // 添加元素
    T get(int index);     // 获取元素
}

// 实现泛型接口 Container,并指定类型参数为 String
public class StringContainer implements Container<String> {
    private List<String> items = new ArrayList<>();

    @Override
    public void add(String item) {
        items.add(item);
    }

    @Override
    public String get(int index) {
        return items.get(index);
    }
}

// 测试泛型接口的实现
public class Main {
    public static void main(String[] args) {
        Container<String> stringContainer = new StringContainer();
        stringContainer.add("Hello");
        System.out.println(stringContainer.get(0)); // 输出:Hello
    }
}

4. 泛型方法

介绍

Java 支持在类中定义泛型方法。泛型方法可以定义在普通类中,也可以定义在泛型类中。在方法定义中使用 <T> 表示这是一个泛型方法,可以接受任意类型的参数。

代码示例

public class GenericMethodExample {
    // 定义一个泛型方法 printArray,类型参数为 T
    public static <T> void printArray(T[] array) {
        for (T item : array) {
            System.out.println(item);
        }
    }

    public static void main(String[] args) {
        // 打印 Integer 数组
        Integer[] intArray = {1, 2, 3, 4};
        printArray(intArray);

        // 打印 String 数组
        String[] strArray = {"A", "B", "C"};
        printArray(strArray);
    }
}

5. 通配符

介绍

Java 泛型提供了通配符 ?,用于表示未知类型。通配符主要用于泛型的读取操作,当我们不确定具体类型但只需要读取数据时可以使用通配符。

代码示例

public class WildcardExample {
    // 使用通配符 ? 打印任意类型的 List
    public static void printList(List<?> list) {
        for (Object item : list) {
            System.out.println(item);
        }
    }

    public static void main(String[] args) {
        List<Integer> intList = Arrays.asList(1, 2, 3);
        List<String> strList = Arrays.asList("Hello", "World");

        printList(intList); // 输出:1 2 3
        printList(strList); // 输出:Hello World
    }
}

6. 上下限

介绍

Java 泛型允许指定类型的上下限:

  • ? extends T:表示类型必须为 TT 的子类,常用于读取操作。
  • ? super T:表示类型必须为 TT 的父类,常用于写入操作。

代码示例

public class BoundExample {
    // 上限:只允许 T 或其子类的 List
    public static void printNumbers(List<? extends Number> list) {
        for (Number num : list) {
            System.out.println(num);
        }
    }

    // 下限:只允许 T 或其父类的 List
    public static void addInteger(List<? super Integer> list) {
        list.add(10);
        list.add(20);
    }

    public static void main(String[] args) {
        List<Integer> intList = new ArrayList<>(Arrays.asList(1, 2, 3));
        printNumbers(intList); // 输出:1 2 3

        List<Number> numList = new ArrayList<>();
        addInteger(numList);
        System.out.println(numList); // 输出:[10, 20]
    }
}

7. 支持的类型与包装类

介绍

Java 泛型只支持引用类型,不支持基本类型(如 intchar 等)。因此,使用泛型时需用包装类(如 IntegerDouble 等)来替代基本类型。

代码示例

public class WrapperExample {
    public static void main(String[] args) {
        // 使用包装类 Integer 替代基本类型 int
        List<Integer> list = new ArrayList<>();
        list.add(10);  // 自动装箱
        list.add(20);
        System.out.println(list); // 输出:[10, 20]
    }
}

8. 泛型的最佳实践

介绍

在实际开发中,合理使用泛型可以极大提升代码的复用性和类型安全性。以下是一些泛型的最佳实践:

  • 在集合中使用泛型:使用集合时添加泛型声明,确保集合中存储的数据类型一致,减少类型转换错误。
  • 避免混用原始类型:原始类型和泛型类型混用可能导致类型转换异常。
  • 使用通配符:当不需要指定泛型类型时,可以使用通配符 ? 以提高代码的灵活性。

代码示例

import java.util.ArrayList;
import java.util.List;

public class BestPracticeExample {
    public static void main(String[] args) {
        // 推荐:在集合中声明泛型类型
        List<String> stringList = new ArrayList<>();
        stringList.add("Hello");

        // 使用通配符打印集合内容
        printCollection(stringList);
    }

    // 使用通配符 ? 表示不限定类型,适用于各种类型的集合
    public static void printCollection(List<?> list) {
        for (Object item : list) {
            System.out.println(item);
        }
    }
}

总结

Java 泛型是一种非常重要的工具,通过参数化类型使代码更具通用性和安全性。无论是泛型类、泛型接口还是泛型方法,合理使用泛型可以避免类型转换错误,提高代码的重用性和安全性。同时,上下限、通配符和包装类等特性使得泛型更加灵活,适用于各种复杂的应用场景。

去1:1私密咨询

系列课程: