Java 泛型:如何在实践中使用尖括号
简介
从 JSE 5.0 开始,泛型被添加到了 Java 语言库中。
Java 中的泛型是什么?
泛型是 Java 实现泛型编程的特殊机制 — 一种描述数据和算法的方法,支持在不改变算法描述的情况下使用不同的数据类型。Oracle 网站有专门针对泛型的单独教程:课程。要理解泛型,首先需要弄清楚为什么需要泛型,泛型有何用途。
教程的“为什么使用泛型?”一节有两个目的:一是在编译时进行更强的类型检查,二是消除对显式强制转换的需要。
让我们在心爱的 Tutorialspoint 在线 Java 编译器中准备进行一些测试。
假设你有以下代码:
import java.util.*;
public class HelloWorld {
public static void main(String []args) {
List list = new ArrayList();
list.add("你好");
String text = list.get(0) + ",世界!";
System.out.print(text);
}
}
这段代码将运行得非常好。但是如果老板过来对我们说,“你好,世界!”这个短语都烂大街了,你只能回复“你好”?我们将删除串联 “,世界!”的代码这似乎是无害的,对不对?但我们在编译时实际会得到错误:
error: incompatible types:Object cannot be converted to String
问题是在我们的 List 中存储 Object。String 是 Object 的后代(因为所有 Java 类都隐式继承 Object),这意味着我们需要显式强制转换,但我们并没有添加。在串联操作期间,将使用对象调用静态 String.valueOf(obj) 方法。最终,它将调用 Object 类的 toString 方法。
换句话说,我们的 List 包含一个 Object。这意味着当我们需要一个特定的类型(不是 Object)时,我们必须自行进行类型转换:
import java.util.*;
public class HelloWorld {
public static void main(String []args) {
List list = new ArrayList();
list.add("你好!");
list.add(123);
for (Object str : list) {
System.out.println("-" + (String)str);
}
}
}
但是,在这种情况下,因为 List 接受对象,所以它不仅可以存储 String,还可以存储 Integer。但最糟糕的是,编译器在这里没有发现任何错误。现在我们将在运行时得到一个错误(称为“运行时错误”)。 错误将是:
java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String
你必须承认这不是很好。
发生此错误都是因为编译器没有能够始终正确猜测程序员意图的人工智能。Java SE 5 引入了泛型,让我们告诉编译器我们的意图 — 我们将使用哪些类型。
我们通过告诉编译器想要什么来修复代码:
import java.util.*;
public class HelloWorld {
public static void main(String []args) {
List<String> list = new ArrayList<>();
list.add("你好!");
list.add(123);
for (Object str : list) {
System.out.println("-" + str);
}
}
}
如你所见,我们不再需要转换成 String。此外,类型参数周围有尖括号。现在编译器不会让我们编译这个类,除非我们删除列表中增加 123 的那一行,因为这是一个 Integer。
编译器会告诉我们这个问题。很多人把泛型称为“语法糖”。他们是对的,因为在泛型被编译之后,确实变成了相同的类型转换。让我们看看编译后类的字节码:一个使用显式强制类型转换,一个使用泛型:
编译后,所有的泛型都被擦除。该操作称为“类型擦除”。 类型擦除和泛型的设计目的是向后兼容旧版本的 JDK,同时允许编译器在新版 Java 中帮助进行类型定义。
阅读全文:https://codegym.cc/s/4434
本作品采用《CC 协议》,转载必须注明作者和本文链接
推荐文章: