← 返回首页

Java泛型详解

📂 java ⏱ 3 min 563 words

什么是泛型

泛型(Generics)是JDK 5引入的特性,它允许在定义类、接口和方法时使用类型参数。泛型提供了编译时类型安全检测,避免了运行时的ClassCastException。

泛型类

泛型类是在类定义时指定类型参数的类。

public class Box<T> {
    private T content;

    public Box(T content) {
        this.content = content;
    }

    public T getContent() {
        return content;
    }

    public void setContent(T content) {
        this.content = content;
    }
}

public class GenericClassDemo {
    public static void main(String[] args) {
        Box<String> stringBox = new Box<>("Hello Generics");
        System.out.println("String Box: " + stringBox.getContent());

        Box<Integer> intBox = new Box<>(12345);
        System.out.println("Integer Box: " + intBox.getContent());
    }
}

多类型参数

泛型类可以有多个类型参数,用逗号分隔。

public class Pair<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;
    }

    @Override
    public String toString() {
        return "Pair{key=" + key + ", value=" + value + "}";
    }
}

public class MultiGenericDemo {
    public static void main(String[] args) {
        Pair<String, Integer> nameAge = new Pair<>("张三", 25);
        Pair<Integer, Boolean> scorePass = new Pair<>(95, true);

        System.out.println(nameAge);
        System.out.println(scorePass);
    }
}

泛型接口

泛型接口是在接口定义时使用类型参数的接口。

public interface Repository<T, ID> {
    T findById(ID id);
    void save(T entity);
    void delete(ID id);
}

public class UserRepository implements Repository<User, Long> {
    @Override
    public User findById(Long id) {
        return new User(id, "张三");
    }

    @Override
    public void save(User entity) {
        System.out.println("保存用户: " + entity.getName());
    }

    @Override
    public void delete(Long id) {
        System.out.println("删除用户ID: " + id);
    }
}

泛型方法

泛型方法是在方法签名中声明自己的类型参数的方法。

public class GenericMethodDemo {
    public static <T> void printArray(T[] array) {
        for (T element : array) {
            System.out.print(element + " ");
        }
        System.out.println();
    }

    public static <T extends Comparable<T>> T findMax(T[] array) {
        T max = array[0];
        for (int i = 1; i < array.length; i++) {
            if (array[i].compareTo(max) > 0) {
                max = array[i];
            }
        }
        return max;
    }

    public static void main(String[] args) {
        Integer[] intArray = {1, 2, 3, 4, 5};
        String[] strArray = {"Java", "Python", "C++"};

        printArray(intArray);
        printArray(strArray);

        System.out.println("最大整数: " + findMax(intArray));
        System.out.println("最大字符串: " + findMax(strArray));
    }
}

类型通配符

通配符用于解决泛型的协变和逆变问题。

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

public class WildcardDemo {
    public static void printList(List<?> list) {
        for (Object item : list) {
            System.out.print(item + " ");
        }
        System.out.println();
    }

    public static double sumOfList(List<? extends Number> list) {
        double sum = 0;
        for (Number num : list) {
            sum += num.doubleValue();
        }
        return sum;
    }

    public static void addNumbers(List<? super Integer> list) {
        list.add(1);
        list.add(2);
        list.add(3);
    }

    public static void main(String[] args) {
        List<String> strings = List.of("Java", "Python", "C++");
        printList(strings);

        List<Integer> integers = List.of(1, 2, 3, 4, 5);
        List<Double> doubles = List.of(1.5, 2.5, 3.5);

        System.out.println("整数和: " + sumOfList(integers));
        System.out.println("浮点数和: " + sumOfList(doubles));

        List<Number> numberList = new ArrayList<>();
        addNumbers(numberList);
        System.out.println("添加后: " + numberList);
    }
}

泛型约束

使用extends关键字可以约束泛型必须继承自某个类或实现某个接口。

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

public class BoundedTypeDemo {
    public static <T extends Comparable<T>> void sortAndPrint(List<T> list) {
        list.sort(T::compareTo);
        System.out.println("排序结果: " + list);
    }

    public static <T extends Number & Comparable<T>> T findMax(List<T> list) {
        T max = list.get(0);
        for (int i = 1; i < list.size(); i++) {
            if (list.get(i).compareTo(max) > 0) {
                max = list.get(i);
            }
        }
        return max;
    }

    public static void main(String[] args) {
        List<String> names = new ArrayList<>(List.of("Charlie", "Alice", "Bob"));
        sortAndPrint(names);

        List<Integer> numbers = new ArrayList<>(List.of(3, 1, 4, 1, 5, 9, 2, 6));
        sortAndPrint(numbers);
    }
}

类型擦除

Java泛型是通过类型擦除实现的,编译后泛型类型信息会被擦除。

public class TypeErasureDemo {
    public static void main(String[] args) {
        List<String> stringList = new ArrayList<>();
        List<Integer> intList = new ArrayList<>();

        System.out.println(stringList.getClass() == intList.getClass());
        System.out.println("运行时类型: " + stringList.getClass().getName());
    }
}

泛型最佳实践

  1. 使用泛型保证类型安全
  2. 避免使用原始类型(Raw Type)
  3. 合理使用通配符处理继承关系
  4. 了解类型擦除的限制
  5. 在API设计中优先使用泛型

总结

泛型是Java类型系统的核心特性,它使代码更加安全、灵活和可重用。理解泛型类、泛型方法、通配符和类型擦除的概念,对于编写高质量的Java代码至关重要。