下面的程序由一个单一的类构成,该类表示一对类型相似的对象。它大量使用了5.0 版的特性,包括泛型、 自动包装、 变长参数(varargs)和 for-each 循环。那么它会打印什么呢?
两次。然而可惜的是,它根本不能通过编译。更糟的是, 编译器的错误消息更是另人困惑:
Pair. java: 26: incompatible types;
found: Object, required: String
for (String s : p.stringList())
^
如果 Pair.stringList 是声明返回 List<Object>的话,那么这个错误消息还是可以明白 的,但是事实是它返回的是List<String>。 究竟是怎么回事呢?
这个十分奇怪的现象是因为程序使用了原生类型(raw type)而引 起的。一个原生类型就是一个没有任何类型参数的泛型类或泛型接口 的名字。 例如, List<E>是一个泛型接口 , List<String> 是一个参数化的类型,而 List 就是一个原生类型。在我们的程序中,唯一用到原生类型的地方就是在 main 方法中对局部变量 p 的
import java.util.*;
public class Pair<T> {
private final T first;
private final T second;
public Pair(T first, T second) {
this.first = first;
this.second = second;
}
public T first() {
return first;
}
public T second() {
return second;
}
public List<String> stringList() {
return Arrays.asList(String.valueOf(first) ,
String.valueOf(second));
}
public static void main(String[] args) {
Pair p = new Pair<Object> (23, "skidoo");
System.out.println(p.first() + " " + p.second());
for (String s : p.stringList())
System.out.print(s + " ");
}
}
这段程序看上去似乎相当简单。它创建了一个对象对,其中第一个元素是一个表示 23 的 Integer 对象, 第二个元素是一个字符串“ skidoo” ,然后这段程序将打印这个对象对的第一个和第二个元素,并用一个空格隔开。最后它循环迭代这些元素的 string 表示,并且再次打印它们,所以这段程序应该打印 23 skidoo两次。然而可惜的是,它根本不能通过编译。更糟的是, 编译器的错误消息更是另人困惑:
Pair. java: 26: incompatible types;
found: Object, required: String
for (String s : p.stringList())
^
如果 Pair.stringList 是声明返回 List<Object>的话,那么这个错误消息还是可以明白 的,但是事实是它返回的是List<String>。 究竟是怎么回事呢?
这个十分奇怪的现象是因为程序使用了原生类型(raw type)而引 起的。一个原生类型就是一个没有任何类型参数的泛型类或泛型接口 的名字。 例如, List<E>是一个泛型接口 , List<String> 是一个参数化的类型,而 List 就是一个原生类型。在我们的程序中,唯一用到原生类型的地方就是在 main 方法中对局部变量 p 的