📌 目录

  1. 什么是泛型?
  2. 泛型的优势
  3. 泛型的基本语法
  4. 泛型类
  5. 泛型方法
  6. 通配符 (Wildcard) 使用
    • 6.1 ? extends T
    • 6.2 ? super T
    • 6.3 ?
  7. 泛型的边界
  8. 泛型的类型推断
  9. 总结
  10. 参考资料
  11. 出站链接

1. 什么是泛型?

Java 泛型是 Java 编程语言的一种机制,允许在类、接口和方法中定义类型参数,从而使得代码在处理不同类型的数据时更加灵活和安全。泛型使得编译器能够提供更强的类型检查,并且减少了类型转换的需要。泛型是 Java 5 引入的,常用于集合框架中。

通过使用泛型,Java 程序可以更加灵活地处理不同类型的对象,同时保证类型安全,从而避免类型转换错误。


2. 泛型的优势

  1. 类型安全:通过泛型,我们可以确保代码在编译时进行类型检查,从而避免在运行时出现类型转换错误。
  2. 代码复用:泛型可以在编写代码时不指定具体的数据类型,从而让代码适用于多种类型,增强了代码的复用性。
  3. 避免强制类型转换:泛型使得我们不再需要在使用集合时进行类型转换,减少了显式转换的错误风险。

3. 泛型的基本语法

泛型的基本语法通过使用尖括号 <> 来定义类型参数。

示例:

// 定义一个泛型类
class Box<T> {
    private T value;

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

    public T getValue() {
        return value;
    }
}

public class Main {
    public static void main(String[] args) {
        Box<Integer> intBox = new Box<>();  // 使用 Integer 类型
        intBox.setValue(10);
        System.out.println(intBox.getValue());

        Box<String> strBox = new Box<>();   // 使用 String 类型
        strBox.setValue("Hello");
        System.out.println(strBox.getValue());
    }
}

在这个例子中,Box 是一个泛型类,T 是一个类型参数。我们可以在使用 Box 类时指定类型(如 IntegerString)。


4. 泛型类

泛型类是指类在定义时通过类型参数化,以便该类可以操作不同类型的数据。类型参数通常在类名后通过尖括号 <> 定义。

示例:

class Pair<K, V> {  // K 和 V 是类型参数
    private K key;
    private V value;

    public Pair(K key, V value) {
        this.key = key;
        this.value = value;
    }

    public K getKey() {
        return key;
    }

    public V getValue() {
        return value;
    }
}

public class Main {
    public static void main(String[] args) {
        Pair<String, Integer> pair = new Pair<>("age", 30);
        System.out.println(pair.getKey() + ": " + pair.getValue());
    }
}

在此示例中,Pair 是一个泛型类,其中 KV 是类型参数。我们可以指定不同的数据类型作为键和值。


5. 泛型方法

泛型方法是在方法声明中定义类型参数。即使方法位于非泛型类中,也可以是泛型方法。

示例:

public class GenericMethod {
    // 泛型方法
    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};
        String[] strArray = {"A", "B", "C"};

        printArray(intArray);  // 打印 Integer 数组
        printArray(strArray);  // 打印 String 数组
    }
}

在此示例中,printArray 是一个泛型方法,它能够接收任何类型的数组并打印其中的元素。


6. 通配符 (Wildcard) 使用

Java 泛型还支持通配符(wildcard),即 ?,它用于表示未知类型。通配符在某些情况下非常有用,特别是当我们希望编写一个方法,可以处理不同类型的泛型参数。

6.1 ? extends T

  • 用于表示上限通配符,意味着类型可以是 T 或其子类型。
public static void printNumbers(List<? extends Number> list) {
    for (Number number : list) {
        System.out.println(number);
    }
}

在这个例子中,? extends Number 表示可以传入 Number 类及其任何子类的 List

6.2 ? super T

  • 用于表示下限通配符,意味着类型可以是 T 或其父类型。
public static void addNumbers(List<? super Integer> list) {
    list.add(10);  // 可以添加 Integer 类型或其父类类型
}

在这个例子中,? super Integer 表示可以传入 Integer 类及其任何父类的 List

6.3 ?

  • ? 表示一个未知类型,通常用于方法的参数中,不关心具体类型。
public static void printList(List<?> list) {
    for (Object obj : list) {
        System.out.println(obj);
    }
}


7. 泛型的边界

Java 泛型允许定义类型的边界。通过设置上限或下限来限制泛型的类型范围。

上限:

public static <T extends Number> void printNumber(T number) {
    System.out.println(number);
}

这表示 T 必须是 Number 或其子类。

下限:

public static <T super Integer> void addInteger(T obj) {
    // 只允许传入 Integer 或其父类类型
}


8. 泛型的类型推断

Java 编译器支持在调用泛型方法时根据传入参数自动推断出泛型类型。通过类型推断,可以简化代码,避免显式指定泛型类型。

示例:

public class GenericTypeInference {
    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};
        printArray(intArray);  // Java 会自动推断出 T 为 Integer 类型
    }
}


9. 总结

  • Java 泛型提供了强大的类型安全和灵活性,它允许我们定义可以操作多种类型数据的类和方法。
  • 泛型有助于提高代码的重用性,同时减少类型转换错误。
  • 泛型类、泛型方法和通配符(wildcard)使得 Java 能够更加通用地处理不同类型的对象。
  • 泛型的边界和类型推断机制使得泛型功能更加灵活,可以定义更复杂的泛型约束。

10. 参考资料


11. 出站链接