Java 中的泛型:综合指南

Java 中的泛型是 Java 5 中引入的一项强大功能,它允许开发人员编写可重用且类型安全的代码。虽然主要用于集合,但它们的应用范围远不止于此。泛型使您能够在编译时指定类型,从而减少运行时错误并增强代码可读性。

泛型的关键概念

  1. 类型 安全

泛型确保只有指定类型的数据才能添加到集合中或在方法中使用,从而防止运行时 ClassCastException。

  1. 代码可重用性

单个泛型类、方法或接口可以处理各种类型的数据,从而减少冗余并促进代码重用。

泛型的工作原理

  1. 泛型类 > 泛型类允许您定义适用于任何数据类型的类。下面是一个示例:
<span style="color:var(--syntax-text-color)"><span style="color:var(--syntax-text-color)"><code>class Box<T> {
    private T item;

    public void setItem(T item) {
        this.item = item;
    }

    public T getItem() {
        return item;
    }
}

public class Main {
    public static void main(String[] args) {
        Box<String> stringBox = new Box<>();
        stringBox.setItem("Hello");
        System.out.println(stringBox.getItem());

        Box<Integer> intBox = new Box<>();
        intBox.setItem(123);
        System.out.println(intBox.getItem());
    }
}

</code></span></span>



  1. 泛型方法 > 泛型方法允许在方法定义中使用类型参数。
<span style="color:var(--syntax-text-color)"><span style="color:var(--syntax-text-color)"><code>class Util {
    public static <T> void printArray(T[] array) {
        for (T element : array) {
            System.out.println(element);
        }
    }
}

public class Main {
    public static void main(String[] args) {
        Integer[] intArray = {1, 2, 3};
        String[] strArray = {"A", "B", "C"};
        Util.printArray(intArray);
        Util.printArray(strArray);
    }
}
</code></span></span>



  1. 有界类型参数 > Type 参数可以使用 extends 或 super 进行约束。
  2. Upper Bound (extends):确保类型是指定类型的子类。
<span style="color:var(--syntax-text-color)"><span style="color:var(--syntax-text-color)"><code>class MathUtils {
    public static <T extends Number> double square(T number) {
        return number.doubleValue() * number.doubleValue();
    }
}

public class Main {
    public static void main(String[] args) {
        System.out.println(MathUtils.square(5));    // Integer
        System.out.println(MathUtils.square(5.5)); // Double
    }
}
</code></span></span>



  • Lower Bound (super):确保类型是指定类型的超类。
  1. 通配符 > 通配符 (?) 表示未知类型,并在使用泛型时提供灵活性。
  2. 无界通配符:
<span style="color:var(--syntax-text-color)"><span style="color:var(--syntax-text-color)"><code>public static void printList(List<?> list) {
    for (Object item : list) {
        System.out.println(item);
    }
}
</code></span></span>



  • 上限通配符:
<span style="color:var(--syntax-text-color)"><span style="color:var(--syntax-text-color)"><code>public static void printNumbers(List<? extends Number> list) {
    for (Number num : list) {
        System.out.println(num);
    }
}
</code></span></span>



  • 下限通配符:
<span style="color:var(--syntax-text-color)"><span style="color:var(--syntax-text-color)"><code>public static void addNumbers(List<? super Integer> list) {
    list.add(10); // Only Integer or its subclass can be added
}
</code></span></span>



泛型和集合

Java Collections Framework 严重依赖泛型来提供类型安全。

  • 示例:对列表使用泛型
<span style="color:var(--syntax-text-color)"><span style="color:var(--syntax-text-color)"><code>import java.util.ArrayList;

public class Main {
    public static void main(String[] args) {
        ArrayList<String> names = new ArrayList<>();
        names.add("Alice");
        names.add("Bob");

        for (String name : names) {
            System.out.println(name);
        }
    }
}
</code></span></span>



  • 示例:将泛型与 Map 结合使用
<span style="color:var(--syntax-text-color)"><span style="color:var(--syntax-text-color)"><code>import java.util.HashMap;

public class Main {
    public static void main(String[] args) {
        HashMap<Integer, String> map = new HashMap<>();
        map.put(1, "One");
        map.put(2, "Two");

        for (Integer key : map.keySet()) {
            System.out.println("Key: " + key + ", Value: " + map.get(key));
        }
    }
}
</code></span></span>



泛型的优点

  1. 类型安全:

通过在编译时捕获类型不匹配来防止运行时错误。

  1. 代码可重用性:

允许为任何类型的编写灵活、可重用的代码。

  1. 性能:

通过消除显式类型转换的需要来减少运行时开销。

泛型的限制

  1. 类型擦除:

泛型是使用类型擦除实现的,因此类型信息在运行时不可用。

  1. 不允许的原始类型:

泛型仅适用于对象。使用 Integer 等包装类来表示 int。

  1. 无静态成员:

泛型类不能使用 type 参数定义静态字段或方法。

结论

Java 中的泛型对于编写健壮、可维护和高效的代码至关重要。通过利用类型安全性和代码可重用性,开发人员可以更有效地处理数据。无论您是使用集合还是创建自定义类,掌握泛型对于高级 Java 开发都至关重要。