Java中的泛型:初学者为何需要及如何使用

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

Java中的泛型:初学者为何需要它们以及如何使用



学习Java时,迟早会遇到泛型这个概念。对于初学者来说,这可能看起来很复杂,但实际上它是该语言中最有用的工具之一。在本文中,我们将详细讲解什么是泛型、为何需要它们以及如何正确使用。本文面向初级开发者。



什么是泛型,没有它会怎样?



泛型是Java的一种机制,允许你对类型进行参数化。简单来说,你可以编写一个类、接口或方法,使其能够处理不同的数据类型,同时在编译时保持严格的类型检查。



想象一下,你想创建一个可以存放任何物品的箱子。在没有泛型的情况下,你需要使用Object:



public class Box {    private Object item;

public void put(Object item) { this.item = item; }

public Object get() { return item; }}


使用这样的类非常麻烦:



Box box = new Box();box.put("Hello");// 取出时需要显式类型转换String text = (String) box.get(); // 存在ClassCastException风险!


如果你不小心放入一个数字,然后试图将其转换为字符串,程序将在运行时崩溃并报错。泛型通过将类型检查移到编译时来解决这个问题。



如何使用泛型:基本语法



让我们用泛型重写我们的Box类:



public class Box<T> {    private T item;

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

public T get() { return item; }}


这里,<T>是类型参数。T是常用的名称(来自单词"Type"),但你可以使用任何字母或单词:E(Element)、K(Key)、V(Value)等。



现在,使用变得安全且优雅:



Box<String> stringBox = new Box<>();stringBox.put("Hello");String text = stringBox.get(); // 无需转换!

// 下面这行代码无法编译:// stringBox.put(123); // 编译错误!


编译器自己知道stringBox只能处理字符串。如果你试图放入一个数字,代码甚至无法编译——你会立即知道错误,而不是在运行时才发现。



集合中的泛型:最需要它们的地方



泛型最常用的地方是Java集合(List、Set、Map等)。在泛型出现之前(Java 5之前),开发者不得不使用存储Object的ArrayList,非常痛苦:



// 旧风格(没有泛型)List list = new ArrayList();list.add("Hello");list.add(123); // 这也能添加!

String item = (String) list.get(0); // 没问题String item2 = (String) list.get(1); // ClassCastException!


有了泛型,一切更简单、更安全:



List<String> names = new ArrayList<>();names.add("Alice");names.add("Bob");// names.add(123); // 编译错误

for (String name : names) { System.out.println(name.toUpperCase()); // 无需转换!}


Map也是如此:



Map<String, Integer> ageMap = new HashMap<>();ageMap.put("Alice", 30);ageMap.put("Bob", 25);

int aliceAge = ageMap.get("Alice"); // 自动拆箱为int


限定类型与通配符:如何让泛型更灵活



有时你需要限制泛型可以接受的类型。这时就需要使用限定类型参数。



例如

博客

书籍推荐