数组
数组与其他种类的容器之间的区别有三方面:效率、类型和保存基本类型的能力。在java中,数组是一种效率最高的存储和随机访问对象引用序列的方式。数组就是一个简单的线性序列,这使得元素访问非常快速,但也损失了其他一些特性。当创建了一个数组对象(将数组本身作为对象看待),数组的大小就被固定了,并且这个数组的生命周期也是不可改变的。通常用移到新数组中。这正式ArrayList类的行为方式。然而这种弹性带来的开销,使得ArrayList比数组效率低得多。
在C++中,容器类vector的确知道自己保存的对象是何类型。不过与java中的数组相比,它有一个缺点:C++中vector的操作符[]不做边界检查,所以可能会越界操作(然而,要问vector有多大是可能的,at()方法的确会执行边界检查)。而在java中,无论使用数组或容器,都有边界检查。如果越界操作就会得到一个RuntimeException异常。这类异常通常说明是程序员的错误,因此你不必自己做越界检查。多说一句,为了速度,C++的vector不会对每次存取做边界检查;而java的数组与容器会因为时刻存在的边界检查带来固定的性能开销。
其他通用的容器类:List、Set和Map,它们不以具体的类型来处理对象。也就是说
,它们将所有对象都按Object类型处理,即java中所有类的基类。从某个角度来说,这种方式很好:你只需要构建一个容器,任意的java对象都可以放入其中。(除开基本类型之外,数组可以放入容器作为使用Java基本包装器类的常量,或者作为包装在你自己的类中的可变值。)这正是数组比通用容器优越的第二点:当你创建一个数组时,它只能保存特定类型(这与第三点相关——数组可以保存基本类型,容器则不能)。这意味着会在编译时做类型检查。以防错误的类型插入数组,或取出数据时弄错类型。当然无论在编译时还是运行时,Java都会阻止你向对象发送不恰当的消息。所以,并不是说哪种方法更不安全,只是如果编译时就能够指出错误,那么程序可以运行得更快,也减少了程序的使用者被异常吓着的可能性。
考虑到效率与类型检查,应该尽可能使用数组。然而,如果要解决更一般化的问题,数组就可能受到过多的限制。——《java编程思想》 对象的集合