Map 是强大的编程工具。尽管并非总是这样,但是在理想情况下,你编写的大部分代码都是在与这些接口打交道, 并且你唯一需要指定所使用的精确类型的地方就是在创建的时候。你可以像下面创建一个 List:
List
因此,你应该创建一个具体类的对象,将其转型为对应的接口,然后在其余的代码中都使用这个接口。这种方式并非总能奏效,因为某些类具有额外的功能,例如,LinkedList 具有在 List 接口中未包含的额外方法,而 TreeMap 也具有在 Map 接口中未包含的方法。如果你需要使用这些方法,就不能将它们向上转型为更通用的接口。
使用 Java SE5 之前的容器的一个主要问题就是编译器允许你向容器中插入不正确的类型。例如,考虑一个 Apple 对象的容器,我们使用最基本最可靠的容器 ArrayList。现在,你可以把 ArrayList 当作 "可以自动扩充自身尺寸的数组" 来看待。使用 ArrayList 相当简单:创建一个实例,用 add() 插入对象,然后用 get() 访问这些对象,此时需要使用索引,就像数组一样,但是不需要方括号。ArrayList 还有一个 size() 方法,使你可以知道已经有多少元素添加了进来,从而不会不小心因素引越界而引发错误。
如果我们把 Apple 和 Orange 都放置在了容器中,然后将它们取出。正常情况下,Java 编译器会报告警告信息,因为没有使用泛型。Apple 和 Orange 类是有区别的,它们除了都是 Object 之外没有任何共性( 如果一个类没有显式地声明继承自哪个类,那么它自动地继承自 Object 的)。因为 ArrayList 保存的是 Object, 因此你不仅可以通过 ArrayList 的 add() 方法将 Apple 对象放进这个容器,还可以添加 Orange 对象,而且无论在编译期还是运行时都不会有问题。
But, 当你在使用 ArrayList 的 get() 方法来取出你认为是 Apple 的对象时,你得到的只是 Object 的引用, 必须将其转型为 Apple,因此,需要将整个表边式括起来, 在调用 Apple 的 id() 方法之前,强制执行转型。否则,你就会得到语法错误。在运行时,当你试图将 Orange 对象转型为 Apple 肘,你就会以前面提及的异常的形式得到一个错误。
使用 Java 泛型来创建类会比较复杂。但是,应用预定义的泛型通常会很简单。例如,要想定义用来保存 Apple 对象的 ArrayList ,你可以声明 ArrayList<Apple>,而不仅仅只是 ArrayList ,其中尖括号括起来的是类型参数(可以有多个), 它指定了这个容器实例可以保存的类型。通过使用泛型, 就可以在编译期防止将错误类型的对象放置到容器中。
List
现在, 编译器可以阻止你将 Orange 放置到 apples 中, 因此它变成了一个编译期错误,而不再是运行时错误。 你还应该注意到, 在将元素从 List 中取出肘, 类型转换也不再是必需的了。 因为 List 知道它保存的是什么类型, 因此它会在调用 get() 时替你执行转型。 这样, 通过使用泛型, 你不仅知道编译器将会检查你放置到容器中的对象类型, 而且在使用容器中的对象时, 可以使用更加清晰的语法。
所有的 Collection 都可以用 foreach 语法遍历,但是被称为 "迭代器" 类会的更灵活。
2018-01-01 内容来自《Java 编程思想》
来源: http://www.bubuko.com/infodetail-2447401.html