不需要类型转换是 Java 泛型的最大优势之一,因为它会在编译时执行类型检查。这将减少ClassCastExceptions 在运行时被抛出的可能性,并且可以产生更健壮的代码。
但我怀疑你完全知道这一点。
每次我查看泛型时,它都会给出
我头疼。我发现最好的部分
Java 是它的简单性和最小化
语法和泛型并不简单
添加大量新的
句法。
起初,我也没有看到泛型的好处。我从 1.4 的语法开始学习 Java(虽然当时 Java 5 已经出来了),当我遇到泛型时,我觉得要写更多的代码,我真的不明白它的好处。
现代 IDE 让使用泛型编写代码变得更加容易。
大多数现代、体面的 IDE 都足够智能,可以帮助编写带有泛型的代码,尤其是代码完成。
这是一个使用HashMap 制作Map<String, Integer> 的示例。我必须输入的代码是:
Map<String, Integer> m = new HashMap<String, Integer>();
确实,为了创建一个新的HashMap,需要输入很多内容。然而,实际上,在 Eclipse 知道我需要什么之前,我只需要输入这么多:
Map<String, Integer> m = new Ha Ctrl+空格
没错,我确实需要从候选列表中选择 HashMap,但基本上 IDE 知道要添加什么,包括泛型类型。使用正确的工具,使用泛型并不算太糟糕。
此外,由于类型是已知的,当从泛型集合中检索元素时,IDE 将表现得好像该对象已经是其声明类型的对象——不需要强制转换让 IDE 知道什么对象的类型是。
泛型的一个关键优势在于它与 Java 5 的新特性配合得很好。下面是一个将整数放入 Set 并计算其总数的示例:
Set<Integer> set = new HashSet<Integer>();
set.add(10);
set.add(42);
int total = 0;
for (int i : set) {
total += i;
}
在那段代码中,存在三个新的 Java 5 特性:
首先,泛型和基元的自动装箱允许以下行:
set.add(10);
set.add(42);
整数10 被自动装箱成一个Integer,其值为10。 (42 也一样)。然后Integer 被扔进已知持有Integers 的Set。尝试抛出 String 会导致编译错误。
接下来,for-each 循环采用所有这三个:
for (int i : set) {
total += i;
}
首先,包含Integers 的Set 用于for-each 循环。每个元素都被声明为int,这是允许的,因为Integer 被拆箱回原语int。并且这种拆箱发生的事实是众所周知的,因为泛型用于指定 Integers 保存在 Set 中。
泛型可以成为将 Java 5 中引入的新功能结合在一起的粘合剂,它只是让编码更简单、更安全。而且大多数时候 IDE 足够聪明,可以帮助您提出好的建议,所以一般情况下,它不会多输入很多内容。
坦率地说,从Set 示例中可以看出,我觉得利用 Java 5 的特性可以使代码更加简洁和健壮。
编辑 - 没有泛型的示例
下面是上面Set 例子的说明,没有使用泛型。这是可能的,但并不完全令人愉快:
Set set = new HashSet();
set.add(10);
set.add(42);
int total = 0;
for (Object o : set) {
total += (Integer)o;
}
(注意:以上代码会在编译时产生未经检查的转换警告。)
使用非泛型集合时,输入到集合中的类型是Object 类型的对象。因此,在本例中,Object 就是 add 编入集合中的内容。
set.add(10);
set.add(42);
在上面几行中,自动装箱正在发挥作用——原始 int 值 10 和 42 被自动装箱到 Integer 对象中,这些对象被添加到 Set 中。但是,请记住,Integer 对象被作为Objects 处理,因为没有类型信息可以帮助编译器知道Set 应该期望什么类型。
for (Object o : set) {
这是至关重要的部分。 for-each 循环起作用的原因是Set 实现了Iterable 接口,该接口返回带有类型信息的Iterator(如果存在)。 (即Iterator<T>。)
但是,由于没有类型信息,Set 将返回一个Iterator,它将Set 中的值返回为Objects,这就是为什么在 for-每个循环必须为Object类型。
现在Object 是从Set 中检索到的,需要手动将其转换为Integer 以执行添加:
total += (Integer)o;
在这里,从Object 到Integer 执行类型转换。在这种情况下,我们知道这将始终有效,但是手动类型转换总是让我觉得它是脆弱的代码,如果在其他地方进行微小的更改可能会损坏。 (我觉得每个类型转换都是一个等待发生的ClassCastException,但我离题了......)
Integer 现在被拆箱成int 并允许执行添加到int 变量total。
我希望我可以说明 Java 5 的新特性可以与非泛型代码一起使用,但它不像使用泛型编写代码那样干净和直接。而且,在我看来,要充分利用 Java 5 中的新特性,应该研究泛型,至少允许编译时检查以防止无效类型转换在运行时引发异常。