Java中的泛型:编写灵活代码,告别ClassCastException

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

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

开始课程

Java中的泛型:如何不再害怕尖括号,开始编写可靠代码

\n\n

在Java世界中,有一件事让新手感到恐惧,几乎不亚于多线程——那就是尖括号 <>。泛型(Generics)看起来神秘,但实际上它是您编写干净、安全代码的最强盟友。让我们通过今天就能应用的示例,来理解Java中的类型化是如何工作的。

\n\n

想象一下:您正在编写一个方法,它需要同时处理数字、字符串以及您自己的类。没有泛型,您将不得不创建数十个重载方法,或者使用Object并手动检查类型。Java泛型优雅且安全地解决了这个问题。

\n\n

为什么没有泛型的代码会变成雷区?

\n\n

让我们回忆一下在泛型出现之前(Java 5之前)程序员是如何生存的。如果您曾经写过不带类型指定的ArrayList,您就知道这种噩梦:

\n\n
List list = new ArrayList();\nlist.add("你好");\nlist.add(42);\nlist.add(new Object());\n\n// 在100行代码之后:\nString text = (String) list.get(1); // 运行时ClassCastException!
\n\n

经典问题:ClassCastException——一种只在运行时才出现的错误。您可能将列表传递给另一个方法,而那里有人确信列表中只有字符串。然后砰!应用程序崩溃了。Java中的泛型将类型检查转移到编译阶段——这就像在您上车之前就生效的保险。

\n\n

Java中的泛型:您需要了解的基本语法

\n\n

泛型的基础是一个简单的想法:我们用类型来参数化类或方法。我们使用类型参数(通常是一个大写字母:T、E、K、V)来代替具体类型。

\n\n

最流行的例子是Java集合:

\n\n
// 没有泛型——危险\nList rawList = new ArrayList();\n\n// 有泛型——安全\nList<String> safeList = new ArrayList<>();\nsafeList.add("Java");\nsafeList.add("泛型");\n// safeList.add(123); // 编译错误!
\n\n

现在编译器知道:safeList内部只能包含字符串。尝试添加数字会在编译阶段引发错误,而不是在运行时。这就是Java类型安全的实际体现。

\n\n

创建您的第一个泛型类

\n\n

假设我们正在编写一个简单的容器来存储一个值。没有泛型,我们将不得不使用Object:

\n\n
public class Box {\n    private Object value;\n\n    public void set(Object value) { this.value = value; }\n    public Object get() { return value; }\n}
\n\n

现在——使用泛型:

\n\n
public class Box<T> {\n    private T value;\n\n    public void set(T value) { this.value = value; }\n    public T get() { return value; }\n}\n\n// 使用:\nBox<Integer> intBox = new Box<>();\nintBox.set(100);\nint value = intBox.get(); // 无需强制转换!
\n\n

请注意:我们不再需要编写(Integer) intBox.get()。编译器自己知道get()将返回Integer。这就是Java泛型的魔力。

\n\n

Java中的类型化:限制与通配符

\n\n

如果没有一些细微之处,泛型就太简单了。其中最主要的是有界类型参数(bounded type parameters)。有时我们需要说:“类型T必须是数字”或“T必须实现Comparable接口”。

\n\n
// T只能是Number或其子类\npublic class Calculator<T extends Number> {\n    private T value;\n\n    public double square() {\n        return value.doub                

博客

书籍推荐