Java编程思想-第16章 数组(要点)

  对数组的基本看法是,你可以创建并组装它们,通过使用整型索引值访问它们的元素,并 且它们的尺寸不能改变。在大多数时候,这就是你需要了解的全部,但是有时你需要在数组上 执行更加复杂的操作,并且你可能需要评估到底是使用数组还是更加灵活的容器。本章将向你 展示如何更加深入地思考数组。

16.1 数组为什么特殊

   Java中有大量其他的方式可以持有对象,那么,到底是什么使数组变得与众不同呢? 数组与其他种类的容器之间的区别有三方面:效率、类型和保存基本类型的能力。在Java 中,数组是一种效率最高的存储和随机访问对象引用序列的方式。数组就是一个简单的线性序 列,这使得元素访问非常快速。但是为这种速度所付出的代价是数组对象的大小被固定,并且 在其生命周期中不可改变。你可能会建议使用 Arraylist(参见第11章),它可以通过创建一个新 实例,然后把旧实例中所有的引用移到新实例中,从而实现更多空间的自动分配。尽管通常应 该首选 Arraylist而不是数组,但是这种弹性需要开销,因此, Arraylist的效率比数组低很多。

   数组和容器都可以保证你不能滥用它们。无论你是使用数组还是容器,如果越界,都会得 到一个表示程序员错误的 Runtimeexception异常。 在泛型之前,其他的容器类在处理对象时,都将它们视作没有任何具体类型。也就是说, 它们将这些对象都当作ava中所有类的根类 Object处理。数组之所以优于泛型之前的容器,就是 因为你可以创建一个数组去持有某种具体类型。这意味着你可以通过编译期检查,来防止插入 错误类型和抽取不当类型。当然,无论在编译时还是运行时,Java都会阻止你向对象发送不恰 当的消息。所以,并不是说哪种方法更不安全,只是如果编译时就能够指出错误,会显得更加 优雅,也减少了程序的使用者被异常吓着的可能性。

16.2 数组是第一级对象

  无论使用哪种类型的数组,数组标识符其实只是一个引用,指向在堆中创建的一个真实对 象,这个(数组)对象用以保存指向其他对象的引I用。可以作为数组初始化语法的一部分隐式 地创建此对象,或者用new表达式显式地创建。只读成员 length是数组对象的一部分(事实上 这是唯一个可以访问的字段或方法),表示此数组对象可以存储多少元素。“[ ]”语法是访问数 组对象唯一的方式。

   下例总结了初始化数组的各种方式,以及如何对指向数组的引用赋值,使之指向另一个数 组对象。此例也说明,对象数组和基本类型数组在使用上几乎是相同的;唯一的区别就是对象 数组保存的是引用,基本类型数组直接保存基本类型的值。

16.3 返回一个数组

  假设你要写一个方法,而且希望它返回的不止一个值,而是一组值。这对于C和C++这样的 语言来说就有点困难,因为它们不能返回一个数组,而只能返回指向数组的指针。这会造成 些问题,因为它使得控制数组的生命周期变得很困难,并且容易造成内存泄漏。 在Java中,你只是直接“返回一个数组”,而无需担心要为数组负责—一只要你需要它,它 就会一直存在,当你使用完后,垃圾回收器会清理掉它。

16.4 多维数组

16.5 数组与泛型

16.6 创建测试数据

16.6.1 Arrays.fill()

16.6.2 数据生存器

16.6.3 从Generator中创建数组

16.7 Arrays实用功能

  在java.util类库中可以找到 Arrays类,它有一套用于数组的 static实用方法,其中有六个基 本方法: equals()用于比较两个数组是否相等( deepEquals()用于多维数组);fill()在本章前面 部分已经论述过了; sort()用于对数组排序; binarySearch()用于在已经排序的数组中查找元 素; toString()产生数组的 String表示; hashCode()产生数组的散列码(你将在第17章中学习它)。 所有这些方法对各种基本类型和 Object类而重载过。此外, Arrays.asList()接受任意的序列或数 组作为其参数,并将其转变为List容器—这个方法在第11章中已经介绍过了。

16.7.1 复制数组

16.7.2 数组的比较

16.7.3 数组元素的比较

16.7.4 数组排序

16.7.5 在已排序的数组中查找

16.8 总结

   在本章中,你看到了Java对尺寸固定的低级数组提供了适度的支持。这种数组强调的是性 能而不是灵活性,并且与C和C++的数组模型类似。在Java的初始版本中,尺寸固定的低级数组 绝对是必需的,不仅是因为Java的设计者选择在Java中要包含基本类型(也是出于性能方面的考 虑),而且还因为那个版本中对容器的支持非常少。因此,在Java的早期版本中,选择包含数组 总是合理的。

  其后的Java版本对容器的支持得到了明显的改进,并且现在的容器在除了性能之外的各个 方面都使得数组相形见绌。就像在本书其他多处地方所叙述的那样,对你来说,性能出问题的 地方通常是无论如何你都无法想象得到的。

   有了额外的自动包装机制和泛型,在容器中持有基本类型就变得易如反掌了,而这也进 步促使你用容器来替换数组。因为泛型可以产生类型安全的容器,因此数组面对这一变化,已 经变得毫无优势了。 就像在本章中描述的,而且当你尝试着使用它们时也会看到,泛型对数组是极大的威胁。 通常,即使当你可以让泛型与数组以某种方式一起工作时(在下一章你将会看到),在编译期你 最终也会得到“不受检查”的警告信息。

   曾经在多个场合,当我和Java语言的设计者们讨论某些特定的示例时,我直接告诉他们 我应该使用容器而不是数组(在这些示例中,我使用数组是为了演示某些具体的技术,因此我 没有选择的余地)。

  所有这些话题都表示:当你使用最近的Java版本编程时,应该“优选容器而不是数组”。只 有在已证明性能成为问题(并且切换到数组对性能提高有所帮助)时,你才应该将程序重构为 使用数组。

posted @ 2018-03-29 15:59  JackYgy  阅读(192)  评论(0)    收藏  举报