Java编程思想(第4版)
作者 : Bruce Eckel
译者 : 陈昊鹏
丛书名 : 计算机科学丛书
出版日期 : 2007-06-18
ISBN : 7-111-21382-6
定价 : 108.00元
教辅资源下载
扩展信息
语种 : 简体中文
页数 : 880
开本 : 16开
原书名 : Thinking in Java (Fourth Edition)
原出版社: Prentice Hall
属性分类: 教材
包含CD :
绝版 :
图书简介

2003年《Software Development》杂志最佳书籍Jolt大奖
  2003年《Java Developer’s Journal》读者选择最佳书籍奖
  2001年《JavaWorld》编辑选择最佳书籍奖
  2000年《JavaWorld》读者选择最佳书籍奖
  1999年《Software Development》杂志最佳产品奖
  1998年《Java Developer’s Journal》编辑选择最佳书籍奖
  本书赢得了全球程序员的广泛赞誉,即使是最晦涩的概念,在Bruce Eckel具有亲和力的文字和小而直接的编程示例面前也会化解于无形。从Java的基础语法到最高级特性(深入的面向对象概念、多线程、自动项目构建、单元测试和调试等),本书都能逐步指导你轻松掌握。

  第4版特点:
  ● 适合初学者与专业人员的经典的面向对象叙述方式,为更新的Java SE5/6增加了新的示例和章节。
  ● 测验框架显示程序输出。
  ● 设计模式贯穿于众多示例中:适配器、桥接器、职责链、命令、装饰器、外观、工厂方法、享元、点名、数据传输对象、空对象、代理、单例、状态、策略、模板方法以及访问者。
  ● 为数据传输引入了XML,为用户界面引入了SWT和Flash。
  ● 重新撰写了有关并发的章节,有助于读者掌握线程的相关知识。
  ● 专门为第4版以及Java SE5/6重写了700多个编译文件中的500多个程序。
  ● 支持网站包含了所有源代码、带注解的解决方案指南、网络日志以及多媒体学习资料。
  ● 覆盖了所有基础知识,同时论述了高级特性。
  ● 详细地阐述了面向对象原理。
  ● 在线可获得Java讲座CD,其中包含Bruce Eckel的全部多媒体讲座。
  ● 在www.MindView.net网站上可以观看现场讲座、咨询和评论。

图书特色

图书前言

一开始,我只是将Java看作“又一种程序设计语言”。从许多方面看,它也的确如此。
  但随着时间流逝,以及对Java的深入研究,我渐渐发现,与我所见过的其他编程语言相比,Java有着完全不同的核心目的。
  程序设计其实是对复杂性的管理:待解决问题的复杂性,以及用来解决该问题的工具的复杂性。正是这种复杂性,导致多数程序设计项目失败。在我所知的所有程序设计语言中,几乎没有哪个将自己的设计目标专注于克服开发与维护程序的复杂性。当然,有些编程语言在设计决策时也曾考虑到复杂性的问题,然而,总是会有其他议题被认为更有必要加入到该语言中。于是不可避免地,正是这些所谓更必要的议题导致程序员最终“头撞南墙”。例如,C++选择向后兼容C(以便更容易吸引C程序员),以及具备C一样的高效率。这两点都是非常有益的设计目标,也确实促成了C++的成功,然而它们却暴露出更多的复杂性问题,而这也使得很多项目不得善终(你自然可以责怪程序员或者项目管理,但是,如果一种语言能够帮助你解决错误,那何乐而不为呢?)。再看一个例子,Visual Basic(VB)选择与Basic绑在一起,而Basic并未被设计为具备可扩展性的程序设计语言,结果呢,建立在VB之上的所有扩展都导致了无法维护的语法。还有Perl,它向后兼容awk、sed、grep,以及所有它打算替代的Unix工具,结果呢,人们开始指责Perl程序成了“不可阅读(write-only)的代码”(即,只要稍过一会儿,你就读不懂刚完成的程序了)。从另一个角度看,在设计C++、VB、Perl以及Smalltalk之类的程序设计语言时,设计师也都为解决复杂性问题做了某种程度的工作。并且,正是解决某类特定问题的能力,成就了它们的成功。
  随着对Java的了解越来越深,Sun对Java的设计目标给我留下了最深刻印象,那就是:为程序员减少复杂性。用他们的话说就是:“我们关心的是,减少开发健壮代码所需的时间以及困难。”在早期,这个目标使得代码的运行并不快(Java程序的运行效率已经改善了),但它确实显著地缩短了代码的开发时间。与用C++开发相同的程序相比,采用Java只需一半甚至更少的开发时间。仅此一项,就已经能节约无法估量的时间与金钱了。然而Java并未止步于此。它开始着手解决日渐变得重要的各种复杂任务,例如多线程与网络编程,并将其作为语言特性或以工具库的形式纳入Java,这使得开发此类应用变得倍加简单。最终,Java解决了一些相当大的复杂性问题:跨平台编程、动态代码修改,甚至是安全的议题。它让你在面对其中任何一个问题时,都能从“举步维艰”到“起立鼓掌”。抛去我们都能看到的性能问题,Java确实非常精彩地履行了它的诺言:极大地提升程序员的生产率。
  同时,Java正从各个方面提升人们相互通讯的带宽。它使得一切都变得更容易:编写程序,团队合作,创建与用户交户的用户界面,在不同类型的机器上运行程序,以及编写通过因特网通信的程序。
  我认为,通讯变革的成果并不见得就是传输巨量的比特。我们所看到的真正变革是人与人之间的通讯变得更容易了:无论是一对一的通信,还是群体与群体之间,甚至整个星球之间的通信。我曾听闻,在足够多的人之间的相互联系之上,下一次变革将是一种全球意识的形成。Java说不定就是促进该变革的工具,至少,它所具备的可能性使我觉得,教授这门语言是非常有意义的一件事情。
  Java SE5与SE6
  本书的第4版得益于Java语言的升级。Sun起初称其为JDK1.5,稍后改作JDK5或J2SE5,最终Sun弃用了过时的“2”,将其改为Java SE5。Java SE5的许多变化都是为了改善程序员的体验。你将会看到,Java语言的设计者们并未完全成功地完成该任务,不过,总的来说,他们已经向正确的方向迈出了一大步。
新版的一个重要目标就是完整地吸收Java SE5/6的改进,并通过本书介绍以及应用这些变化。这意味着本书基本可以称之为“只限Java SE5/6”。并且,书中的多数代码并没有经过老版本的Java编译测试,所以如果你使用的是老版本的Java,编译可能会报错并中止。不过,我觉得这样利大于弊。
  如果你不得不采用老版本的Java,我仍然为你在www.MindView.net提供了本书早期版本的免费下载。基于某些原因,我决定不提供本书当前版本的免费电子版。
  Java SE6
  本书是一个非常耗时的,且具有里程碑意义的一个项目。就在本书出版之前,Java SE6(代号野马mustang)已经发布了beta版。虽然Java SE6中的一些小变化,对书中的代码示例有一点影响,但其主要的改进对本书的绝大部分内容并没有影响。因为Java SE6主要关注于提升速度,以及改进一些(不在本书讨论范围之内)类库的特性。
  本书中代码全部用Java SE6的一个发布候选版(RC)进行过测试,因此我不认为Java SE6正式发布时会有什么变化能够影响本书的内容。如果到时真的有什么重要的改变,我将更新本书中的代码,你可以通过www.MindView.net下载。
本书的封面已经指出,本书面向“Java SE5/6”。也就是说本书的撰写“面向Java SE5及其为Java语言引入的重大变化,同时也适用于Java SE6”。
  第4版
  为一本书写作新版时,作者最满意的是:把事情做得“恰如其分”。这是我从本书上一个版本发布以来所学到的东西。通常而言,这种见识正如谚语所云,“学习就是从失败中汲取教训。”并且,我也借机进行了一些修订。与往常一样,一个新的版本必将带来引人入胜的新思想。此时,新发现带来的喜悦,采用比以往更好的形式表达思想的能力,已经远远超过了可能引入的小错误。
  这也是对不断在我脑中盘旋低语着的一种挑战,那就是让持有本书老版本的读者也愿意购买新的版本。这些促使着我尽可能改进,重写,以及重新组织内容,为热忱的读者们献上一本全新的,值得拥有的书。
  改变
  此版本中将不再包含以往本书中所携带的CD光盘。该CD中的重要部分《Thinking in C》的多媒体教程(由Chuck Allison为MindView创建),现在提供了可下载的Flash版本。该教程是为不熟悉C语法的读者所准备的。虽然,本书用了两章对语法做了较为完整的介绍,然而对于没有相应背景知识的读者而言,这也许仍然不够。而《Thinking in C》正是为了帮助这些读者提升到必要的程度。
  完全重写了“并发”这一章(以前称为“多线程”),以符合Java SE5并发类库的重大改变。它将为读者了解并发的核心思想打下基础。如果没有这些核心的基础知识,读者很难理解关于线程的更复杂的议题。我花了很多个月撰写这一章,深陷“并发”的地狱之中,最终,这一章不仅涵盖了基础知识,而且大胆地引入了一些高级议题。
  而对于Java SE5所具有的每一个重大的新特性,本书都有一个新的章节与之对应。其他的新特性则加入到了原有的章节中。我还一直在研究设计模式,因此在本书中,也介绍了设计模式的相关内容。
  本书经历了重大的重组。这大多源自教授Java的过程,以及我对于“章节”的意义的重新思考。以前,我会不假思索地认为,每个“章节”应该包含一个“足够大的”主题。但是,在我教授设计模式的时候,我发现,如果每次只介绍一个模式(即使讲课的时间很短),然后立刻组织大家做练习,此时那些学员们的表现是最好的(我发现,这种节奏对于我这个老师而言也更有乐趣)。因此,在这一版中,我试着打破按主题划分章节的做法,也不理会章节的长度。我想,这也是一个改进。
  我同样也认识到代码测试的重要性。必须要有一个内建的测试框架,并且每次你开发系统时都必须进行测试。否则,根本没有办法知道代码可靠与否。为了做到这一点,我开发了一个测试框架以显示和验证本书中每一个程序的输出结果。(该框架是用Python编写的,你可以在www.MindView.net找到可下载的代码。)关于测试的话题在附录中有讨论,你可以在http://MindView.net/Books/BetterJava找到。其中还包含了其他一些基本技术,我认为所有程序员都应该将它们加入到自己的工具箱中。
  此外,我还仔细检查了书中的每一个示例,并且问我自己,“我为什么采用这种方式实现?”对大多数的示例,我都做了一定程度的修订与改进,使得这些示例更加贴切。同时,也传达出我所认为的Java编程中的最佳实践(至少起到抛砖引玉的作用)。许多以前的示例都经过了重新设计与重新编写,同时,删除了不再有意义的示例,也添加了新的示例。
  读者们为此书的前三个版本提出了许多许多精彩的意见。这自然使我觉得非常高兴。不过,偶尔读者也会有抱怨,例如有读者埋怨“本书太长了”。对我而言,如果“页数太多”是你唯一的苦恼,那这真令人哭笑不得。(据说奥地利皇帝曾抱怨莫扎特的音乐“音符太多”!我可不是想把自己比作莫扎特。)此外,我只能猜测,发出这种抱怨的读者还不了解Java语言的博大精深,而且也没有看过这一领域的其他书籍。无论如何,在这一版中,我已经删减了过时无用,或不再重要的内容。总的来说,我已经尽我所能仔细复查了全书,进行了必要的增删与改进。对于删除旧的章节,我还是挺放心的。因为原始的材料在网站上都有(www.MindView.net)。本书从第一版到第三版,以及本书的附录,都可以从此网站上下载。
  对于仍然不能接受本书篇幅的读者,我向你们道歉。请相信,我已经尽我所能精简本书的长度了。
  封面图片的故事
  《Thinking in Java》的封面创作灵感来自于美国的 Arts & Crafts运动。该运动始于世纪之交,并在1900 到1920年间达到顶峰。它起源于英格兰,是对工业革命带来的机器产品和维多利亚时代高度装饰化风格的回应。Arts & Crafts强调简洁设计,而回归自然是其整个运动的核心,注重手工制造及推崇个性化设计,可是它并不回避使用现代工具。这和我们现今的情形有很多相似之处:世纪之交,从计算机革命的最初起源到对个人来说更精简、更意味深长的事物的演变,以及对软件开发技能而不仅是生产程序代码的强调。
  我以同样的眼光看待Java:尝试将程序员从操作系统机制中解放出来,朝着“软件艺师”的方向发展。
  我和封面设计者自孩提时代就是朋友,我们从这次运动中获得灵感,并且都拥有源自那个时期的(或受那个时期启发而创作的)家具、台灯和其他作品。
  这个封面暗示的另一主题是一个收集盒,博物学家可以用它来展示他们保存的昆虫标本。这些昆虫可以看作是对象,并放置到“盒”这个对象当中,而盒对象又放置到“封面对象”当中,这形象地说明了面向对象程序设计中最为基本的“集合”概念。当然,程序员可能会不禁联想到“程序缺陷(bug)”;这些虫子被捕获,并假设在标本罐中被杀死,最后禁闭于一个展示盒中,似乎暗示Java有能力发现、显示和制服程序缺陷(事实上,这也是它最为强大的属性之一)。
  在本版中,我创造了一幅水彩画,你可以在封面的背景中看到它。
  致谢
  首先感谢和我一起开研讨课、提供咨询和开发教学计划的这些合作者:Dave Bartlett、Bill Venners、Chuck Allison、Jeremy Meyer和 Jamie King。在我转而不停地竭力为那些像我们一样的独立人群开发在一起协同工作的最佳模式的时候,你们的耐心让我感激不已。
  最近,无疑是因为有了Internet,我可以和极其众多的人一起合作,他们协助我一起努力,他们通常是在家办公。过去,我可能必须为这些人提供相当大的办公空间,不过由于现在有了网络、传真以及电话,我不需要额外的开销就可以从他们的帮助中受益。在我尽力学习更好地与其他人相处的过程中,你们都对我很有帮助,并且我希望继续学习怎样使我的工作能够通过借鉴他人的成果而变得更出色。Paula Steuer在接管我偶尔的商务活动时发挥了不可估量的价值,他使它们变得井井有条(Paula,感谢你在我懈怠时对我的鞭笞)。Jonathan Wilcox, Esq.详细审视了我公司的组织结构,推翻了每一块可能隐藏祸害的石头,并且使所有事情都条理化和合法化了,这让我们心服口服。感谢你的细心和耐心。Sharlynn Cobaugh使自己成为声音处理的专家,她是创建多媒体培训CD ROM和解决其他问题的精英成员之一。感谢你在面临难于处理的计算机问题时的坚定不移。在布拉格Amaio的人们也提出了一些方案来帮助我。Daniel Will-Harris最先受到在网上工作的启发,因此他当然是我所有设计方案的主要人物。
  多年以来,Gernal Weinberg通过他的学术会议和研讨会,已经成为了我非正式的教练和导师,我十分感谢他。
  Ervin Varga在第4版的技术纠正方面提供了巨大的帮助——尽管其他人在各个章节和示例方面也帮助良多,但是Ervin是本书最主要的技术复审者,他还承担了第4版的解决方案指南的重写任务。Ervin发现的错误和对本书所作的完善对本书来说价值连城。他对细节的投入和关注程度令人惊异,他是我所见过的远远超过其他人的最好的技术读者。感谢你,Ervin。
  我在Bill Venners的www.Artima.com上的weblog,已经成为了当我需要交流思想时的一种解决之道。感谢那些通过提交评论帮助我澄清概念的人们,包括James Watson、Howard Lovatt、Michael Barker以及其他一些人,特别是那些在泛型方面提供帮助的人。
  感谢Mark Welsh不懈的帮助。
  Evan Cofsky一如既往地提供了有力的支持,他埋头处理了大量晦涩的细节,从而建立和维护了基于Linux的Web服务器,并保持MindView服务器始终处于协调和安全的状态。
  一份特别的感谢要送给我的新朋友,咖啡,它为本项目产生了几乎无穷无尽的热情。当人们来到MindView研讨课时,科罗拉多州Crested Butte的Camp4 Coffee已经成为了标准住所,并且在研讨课中间休息期间,它是我所遇到的最好的饮食场所。感谢我的密友Al Smith,是他使这里成为如此好的一个地方,成为Crested Butte培训期间一个如此有趣和愉快的场所。还要感谢Camp4的所有泡吧常客们,很高兴他们总是为我们提供一些饮料。
  感谢Prentice Hall的人们不断地为我提供我所需要的一切,并容忍我所有的特殊需求,而且不厌其烦地帮我把所有事情都搞定。
  在我的开发过程中,有些工具已经被证明是无价的;但每次使用它们时都会非常感激它们的创建者。Cygwin (http://www.cygwin.com)为我解决了无数Windows不能解决的问题,并且每天我都会变得更加依赖它(如果在15年前当我的头脑因使用Gnu Emacs而搞得发懵的时候,能有这些该多好啊)。IBM的Eclipse (http://www.eclipse.org)对开发社区做出了真正杰出的贡献,并且随着它的不断升级,我期望能看到它的更伟大之处(IBM是怎样成为潮流所向的?我肯定错过了一份备忘录)。而JetBrains IntelliJ Idea则继续开阔着开发工具的创新之路。
  我一开始就将Sparxsystems的Enterprise Architecture用于本书,并且它很快就成为了我选择的UML工具。Marco Hunsicker的Jalopy代码格式化器(www.triemax.com)在大量的场合都派上了用场,而且Marco在将其配置成满足我的特殊需求方面也提供了大量的帮助。我还发现Slava Pestov的JEdit及其插件经常会显得很有用(www.jedit.org),并且对于研讨课来说,它是非常适合初学者的编辑器。
  当然,如果我在其他地方强调得还不够的话,我得再次重申,我经常使用Python(www.Python.org)解决问题,在我的密友Guido Van Rossum和PythonLabs那些身材臃肿愚笨的天才人物的智慧结晶的基础上,我花费了好几天的时间进行冲刺(Tim Peters,我现在已经把你借的鼠标加了个框,正式命名为TimBotMouse)。你们这伙人必须到更健康的地方去吃午餐。(还要感谢整个Python社区,他们是一帮令人吃惊的群体。)
  很多人向我发送修正意见,我感激所有这些人,第1版特别要感谢:Kevin Raulerson(发现无数的程序缺陷),Bob Resendes(简直难以置信),John Pinto、Joe Dante、Joe Sharp(三位都难以置信),David Combs(校正了许多语法和声明),Dr. Robert Stephenson、John Cook、Franklin Chen、Zev Griner、David Karr、Leander A. Stroschein、Steve Clark、Charles A、Lee、Austin Maher、Dennis P. Roth、Roque Oliveira、Douglas Dunn、Dejan Ristic、Neil Galarneau、David B. Malkovsky、Steve Wilkinson以及许许多多的人。本书第1版在欧洲发行时,Marc Meurrens在电子版宣传和制作方面做出了巨大的努力。
  感谢在本书第2版中使用Swing类库帮助我重新编写示例的人们,以及其他助手—Jon Shvarts、Thomas Kirsch、Rahim Adatia、Rajesh Jain、Ravi Manthena、Banu Rajamani、Jens Brandt、Nitin Shivaram、Malcolm Davis,还有所有表示支持的人。
  在第4版中,Chris Grindstaff对SWT一节的撰写提供很多帮助,而Sean Neville为我撰写了Flex一节的第一稿。
  每当我认为我已经理解了并发编程时,又会有新的奇山险峰等待我去征服。感谢Brian Goetz帮助我克服了在撰写新版本的“并发”一章时遇到的种种艰难险阻,并发现了其中所有的缺陷(我希望如此!)
  对Delphi的理解使我更容易理解Java,这一点儿都不奇怪,因为它们有许多概念和语言设计决策是相通的。我的懂Delphi的朋友们给我提供了许多帮助,使我能够洞察一些非凡的编程环境。他们是Marco Cantu(另一个意大利人-难道会说拉丁语的人在学习Java时有得天独厚的优势?)、Neil Rubenking(直到发现喜欢计算机之前,他一直都在做瑜珈/素食/禅道),当然还有Zack Urlocker(最初的Delphi产品经理),他是我游历世界时的好伙伴。我们都很感激Anders Hejlsberg的卓越才华,他在C#领域不懈地奋斗着(正如你将在本书中看到的,C#是 Java SE5主要的灵感之一)。
  我的朋友Richard Hale Shaw(以及Kim)的洞察力和支持都很有帮助。Richard和我花了数月时间将教学内容合并到一起,并为参加学习的学生设计出一套完美的学习体验。
  书籍设计、封面设计以及封面照片是由我的朋友Daniel Will-Harris制作的。他是一位著名的作家和设计家(http://www.WillHarris.com),在计算机和桌面排版发明之前,他在初中的时候就常常摆弄刮擦信(rub-on letter),他总是抱怨我的代数含糊不清。然而,要声明的是,是我自己制作的照排好的(camera-ready)页面,所以所有排字错误都应该算到我这里。我是用Microsoft Word XP for Windows来编写这本书的,并使用Adobe Acrobat制作照排页面的。本书是直接从Acrobat PDF文件创建而来的。电子时代给我们带来了厚礼,我恰巧是在海外创作了本书第1版和第2版的最终稿—第1版是在南非的开普敦送出的,而第2版却是在布拉格寄出的。第3版和第4版则来自科罗拉多州的Crested Butte。正文字体是Georgia,而标题是Verdana。封面字体是ITC Rennie Machintosh。
  特别感谢我的所有老师和我的所有学生(他们也是我的老师)。
  Molly,在我从事这一版的写作时总是坐在我腿上,为我提供了她特有的温软而毛茸茸的支持。
  曾向我提供过支持的朋友包括(当然还不止他们):Patty Gast(Masseuse extraordinary),Andrew Binstock,SteveSinofsky,JD Hildebrandt,Tom Keffer,Brian McElhinney,Brinkley Barr,《Midnight Engineering》杂志社的Bill Gates,Larry Constantine和Lucy Lockwood,Gene Wang,Dave Mayer,David Intersimone,Chris和Laura Strand,Almquists,Brad Jerbic,Marilyn Cvitanic,Mark Mabry,Dave Stoner,Cranstons,Larry Fogg,Mike Sequeira,Gary Entsminger,Kevin 和Sonda Donovan,Joe Lordi,Dave和Brenda Bartlett,Patti Gast,Blake,Annette&Jade, Rentschlers,Sudeks,Dick,Patty和Lee Eckel,Lynn和Todd以及他们的家人。当然还有我的父亲和母亲。

封底文字

2003年《Software Development》杂志最佳书籍Jolt大奖 2003年《Java Developer’s Journal》读者选择最佳书籍奖 2001年《JavaWorld》编辑选择最佳书籍奖 2000年《JavaWorld》读者选择最佳书籍奖 1999年《Software Development》杂志最佳产品奖 1998年《Java Developer’s Journal》编辑选择最佳书籍奖 本书赢得了全球程序员的广泛赞誉,即使是最晦涩的概念,在Bruce Eckel具有亲和力的文字和小而直接的编程示例面前也会化解于无形。从Java的基础语法到最高级特性(深入的面向对象概念、多线程、自动项目构建、单元测试和调试等),本书都能逐步指导你轻松掌握。 第4版特点: ● 适合初学者与专业人员的经典的面向对象叙述方式,为更新的Java SE5/6增加了新的示例和章节。 ● 测验框架显示程序输出。 ● 设计模式贯穿于众多示例中:适配器、桥接器、职责链、命令、装饰器、外观、工厂方法、享元、点名、数据传输对象、空对象、代理、单例、状态、策略、模板方法以及访问者。 ● 为数据传输引入了XML,为用户界面引入了SWT和Flash。 ● 重新撰写了有关并发的章节,有助于读者掌握线程的相关知识。 ● 专门为第4版以及Java SE5/6重写了700多个编译文件中的500多个程序。 ● 支持网站包含了所有源代码、带注解的解决方案指南、网络日志以及多媒体学习资料。 ● 覆盖了所有基础知识,同时论述了高级特性。 ● 详细地阐述了面向对象原理。 ● 在线可获得Java讲座CD,其中包含Bruce Eckel的全部多媒体讲座。 ● 在www.MindView.net网站上可以观看现场讲座、咨询和评论。

作者简介

Bruce Eckel:Bruce Eckel:  Bruce Eckel 是MindView公司 (www.MindView.net) 的总裁,向客户提供软件咨询和培训。他是C++标准委员会拥有表决权的成员之一。他也是《Java编程思想》(该书第3版影印版及翻译版已由机械工业出版社引进出版)、《C++编程思想 第1卷》及其他C++著作的作者,已经发表了150多篇论文 (其中有许多C++语言方面的论文) ,他经常参加世界各地的研讨会并进行演讲。

译者简介

陈昊鹏:暂无简介

译者序

时隔两年多,《Java编程思想(第4版)》的中文版又要和广大Java程序员和爱好者们见面了。这是Java语言本身不断发展和完善的必然要求,也是本书作者Bruce Eckel孜孜不倦的创作激情和灵感所结出的硕果。
  《Java编程思想(第4版)》以Java最新的版本JDK5.0为基础,在第3版的基础上,添加了最新的语言特性,并且对第3版的结构进行了调整,使得所有章节的安排更加遵照循序渐进的特点,同时每一章的内容在分量上也都更加均衡,这使读者能够更加容易地阅读本书并充分了解每章所讲述的内容。在这里我们再次向Bruce Eckel致敬,他不但向我们展示了什么样的书籍才是经典书籍,而且还展示了经典书籍怎样才能精益求精,长盛不衰。
  Java已经成为了编程语言的骄子。我们可以看到,越来越多的大学在教授数据结构、程序设计和算法分析等课程时,选择以Java语言为载体。这说明Java语言已经是人们构建软件系统时主要使用的一种编程语言。但是,掌握好Java语言并不是一件可以轻松完成的任务,如何真正掌握Java语言,从而编写出健壮的、高效的以及灵活的程序是Java程序员们面临的重大挑战。
  《Java编程思想(第4版)》就是一本能够让Java程序员轻松面对这一挑战,并最终取得胜利的经典书籍。本书深入浅出、循序渐进地把我们领入Java的世界,让我们在不知不觉中就学会了用Java的思想去考虑问题、解决问题。本书不仅适合Java的初学者,更适合于有经验的Java程序员,这正是本书的魅力所在。但是,书中并没有涵盖Java所有的类、接口和方法,因此,如果你希望将它当作Java的字典来使用,那么显然就要失望了。
  我们在翻译本书的过程中力求忠于原著,为了保持连贯性,对原书第3版中仍然保持不变的部分,我们对译文除了个别地方之外,也没做修改。对于本书中出现的大量的专业术语尽量遵循标准的译法,并在有可能引起歧义之处注有英文原文,以方便读者对照与理解。
  全书由陈昊鹏翻译,郭嘉也参与了部分翻译工作。由于水平有限,书中出现错误与不妥之处在所难免,恳请读者批评指正。


  译  者
  2007年5月

图书目录

出版者的话
专家指导委员会
读者评论
关于《Thinking in C++》
译者序
译者简介
前言
绪论
第1章  对象导论 1
1.1  抽象过程 1
1.2  每个对象都有一个接口 2
1.3  每个对象都提供服务 4
1.4  被隐藏的具体实现 4
1.5  复用具体实现 5
1.6  继承 6
1.6.1  “是一个”与“像是一个”关系 8
1.7  伴随多态的可互换对象 8
1.8  单根继承结构 11
1.9  容器 11
1.9.1  参数化类型 12
1.10  对象的创建和生命期 13
1.11  异常处理:处理错误 14
1.12  并发编程 14
1.13  Java与Internet 15
1.13.1  Web是什么 15
1.13.2  客户端编程 16
1.13.3  服务器端编程 19
1.14  总结 20
第2章  一切都是对象 21
2.1  用引用操纵对象 21
2.2  必须由你创建所有对象 22
2.2.1  存储到什么地方 22
2.2.2  特例:基本类型 23
2.2.3  Java中的数组 24
2.3  永远不需要销毁对象 24
2.3.1  作用域 24
2.3.2  对象的作用域 25
2.4  创建新的数据类型:类 25
2.4.1  字段和方法 26
2.5  方法、参数和返回值 27
2.5.1  参数列表 27
2.6  构建一个Java程序 28
2.6.1  名字可见性 28
2.6.2  运用其他构件 28
2.6.3  static 关键字 29
2.7  你的第一个Java程序 30
2.7.1  编译和运行 31
2.8  注释和嵌入式文档 32
2.8.1  注释文档 32
2.8.2  语法 33
2.8.3  嵌入式HTML 33
2.8.4  一些标签示例 34
2.8.5  文档示例 35
2.9  编码风格 36
2.10  总结 36
2.11  练习 37
第3章  操作符 38
3.1  更简单的打印语句 38
3.2  使用Java操作符 39
3.3  优先级 39
3.4  赋值 39
3.4.1  方法调用中的别名问题 40
3.5  算术操作符 41
3.5.1  一元加、减操作符 43
3.6  自动递增和递减 43
3.7  关系操作符 44
3.7.1  测试对象的等价性 44
3.8  逻辑操作符 45
3.8.1 短路 46
3.9  直接常量 47
3.9.1  指数记数法 48
3.10  按位操作符 49
3.11  移位操作符 49
3.12  三元操作符 if-else 52
3.13  字符串操作符 + 和 += 53
3.14 使用操作符时常犯的错误 54
3.15  类型转换操作符 54
3.15.1  截尾和舍入 55
3.15.2  提升 56
3.16  Java没有sizeof 56
3.17  操作符小结 56
3.18  总结 63
第4章  控制执行流程 64
4.1  true和false 64
4.2  if-else 64
4.3  迭代 65
4.3.1  do-while 65
4.3.2  for 66
4.3.3  逗号操作符 67
4.4  Foreach语法 67
4.5  return 69
4.6  break和 continue 69
4.7  臭名昭著的goto 70
4.8  switch 73
4.9  总结 75
第5章  初始化与清理 76
5.1  用构造器确保初始化 76
5.2  方法重载 77
5.2.1  区分重载方法 79
5.2.2  涉及基本类型的重载 79
5.2.3  以返回值区分重载方法 82
5.3  默认构造器 83
5.4  this关键字 84
5.4.1  在构造器中调用构造器 85
5.4.2  static的含义 86
5.5  清理:终结处理和垃圾回收 87
5.5.1  finalize()的用途何在 87
5.5.2  你必须实施清理 88
5.5.3  终结条件 88
5.5.4  垃圾回收器如何工作 89
5.6  成员初始化 91
5.6.1  指定初始化 93
5.7  构造器初始化 94
5.7.1  初始化顺序 94
5.7.2  静态数据的初始化 95
5.7.3  显式的静态初始化 96
5.7.4  非静态实例初始化 97
5.8  数组初始化 98
5.8.1  可变参数列表 102
5.9  枚举类型 105
5.10  总结 107
第6章  访问权限控制 109
6.1  包:库单元 110
6.1.1  代码组织 110
6.1.2  创建独一无二的包名 111
6.1.3  定制工具库 114
6.1.4  用 import改变行为 115
6.1.5  对使用包的忠告 115
6.2  Java访问权限修饰词 116
6.2.1  包访问权限 116
6.2.2  public:接口访问权限 116
6.2.3  private:你无法访问 118
6.2.4  protected:继承访问权限 118
6.3  接口和实现 120
6.4  类的访问权限 121
6.5  总结 123
第7章  复用类 125
7.1  组合语法 125
7.2  继承语法 127
7.2.1  初始化基类 129
7.3  代理 130
7.4  结合使用组合和继承 132
7.4.1  确保正确清理 133
7.4.2  名称屏蔽 135
7.5  在组合与继承之间选择 137
7.6  protected关键字 138
7.7  向上转型 139
7.7.1  为什么称为向上转型 139
7.7.2  再论组合与继承 140
7.8  final关键字 140
7.8.1  final 数据 140
7.8.2  final 方法 143
7.8.3  final 类 144
7.8.4  有关final的忠告 145
7.9  初始化及类的加载 145
7.9.1  继承与初始化 146
7.10  总结 147
第8章  多态 148
8.1  再论向上转型 148
8.1.1  忘记对象类型 149
8.2  转机 150
8.2.1  方法调用绑定 150
8.2.2  产生正确的行为 151
8.2.3  可扩展性 153
8.2.4  缺陷:“覆盖”私有方法 156
8.2.5  缺陷:域与静态方法 156
8.3  构造器和多态 157
8.3.1  构造器的调用顺序 157
8.3.2  继承与清理 159
8.3.3  构造器内部的多态方法的行为 162
8.4  协变返回类型 164
8.5  用继承进行设计 165
8.5.1  纯继承与扩展 166
8.5.2  向下转型与运行时类型识别 167
8.6  总结 168
第9章  接口 169
9.1  抽象类和抽象方法 169
9.2  接口 172
9.3  完全解耦 174
9.4  Java中的多重继承 178
9.5  通过继承来扩展接口 180
9.5.1  组合接口时的名字冲突 181
9.6  适配接口 181
9.7  接口中的域 183
9.7.1  初始化接口中的域 184
9.8  嵌套接口 185
9.9  接口与工厂 186
9.10  总结 188
第10章  内部类 190
10.1  创建内部类 190
10.2  链接到外部类 191
10.3  使用.this与.new 193
10.4  内部类与向上转型 194
10.5  在方法和作用域内的内部类 195
10.6  匿名内部类 196
10.6.1  再访工厂方法 199
10.7  嵌套类 201
10.7.1  接口内部的类 202
10.7.2  从多层嵌套类中访问外部类的
成员 203
10.8  为什么需要内部类 204
10.8.1  闭包与回调 205
10.8.2  内部类与控制框架 207
10.9  内部类的继承 212
10.10  内部类可以被覆盖吗 212
10.11  局部内部类 214
10.12  内部类标识符 215
10.13  总结 215
第11章  持有对象 216
11.1  泛型和类型安全的容器 216
11.2  基本概念 219
11.3  添加一组元素 220
11.4  容器的打印 221
11.5 List 223
11.6  迭代器 226
11.6.1  ListIterator 227
11.7  LinkedList 228
11.8  Stack 229
11.9  Set 231
11.10  Map 233
11.11  Queue 236
11.11.1  PriorityQueue 237
11.12  Collection和Iterator 238
11.13  Foreach与迭代器 241
11.13.1  适配器方法惯用法 243
11.14  总结 245
第12章  通过异常处理错误 248
12.1  概念 248
12.2  基本异常 249
12.2.1  异常参数 250
12.3  捕获异常 250
12.3.1  try块 250
12.3.2  异常处理程序 250
12.4  创建自定义异常 251
12.4.1  异常与记录日志 253
12.5  异常说明 256
12.6  捕获所有异常 256
12.6.1  栈轨迹 257
12.6.2  重新抛出异常 258
12.6.3  异常链 260
12.7  Java标准异常 263
12.7.1  特例:RuntimeException 263
12.8  使用finally进行清理 264
12.8.1  finally用来做什么 265
12.8.2  在return中使用finally 267
12.8.3  缺憾:异常丢失 268
12.9  异常的限制 269
12.10  构造器 271
12.11  异常匹配 275
12.12  其他可选方式 276
12.12.1  历史 277
12.12.2  观点 278
12.12.3  把异常传递给控制台 279
12.12.4  把“被检查的异常”转换为
“不检查的异常” 279
12.13  异常使用指南 281
12.14  总结 281
第13章  字符串 283
13.1  不可变String 283
13.2  重载“+”与StringBuilder 283
13.3  无意识的递归 287
13.4  String上的操作 288
13.5  格式化输出 289
13.5.1  printf() 289
13.5.2  System.out.format() 289
13.5.3  Formatter类 290
13.5.4  格式化说明符 291
13.5.5  Formatter转换 292
13.5.6  String.format() 294
13.6  正则表达式 295
13.6.1  基础 295
13.6.2  创建正则表达式 297
13.6.3  量词 299
13.6.4  Pattern和Matcher 300
13.6.5  split() 305
13.6.6  替换操作 306
13.6.7  reset() 307
13.6.8  正则表达式与Java I/O 307
13.7  扫描输入 309
13.7.1  Scanner定界符 310
13.7.2  用正则表达式扫描 311
13.8  StringTokenizer 312
13.9  总结 312
第14章  类型信息 313
14.1  为什么需要RTTI 313
14.2  Class对象 314
14.2.1  类字面常量 318
14.2.2  泛化的Class引用 320
14.2.3  新的转型语法 322
14.3  类型转换前先做检查 322
14.3.1  使用类字面常量 327
14.3.2  动态的instanceof 329
14.3.3  递归计数 330
14.4  注册工厂 331
14.5  instanceof 与 Class的等价性 333
14.6  反射:运行时的类信息 334
14.6.1  类方法提取器 335
14.7  动态代理 337
14.8  空对象 341
14.8.1  模拟对象与桩 346
14.9  接口与类型信息 346
14.10  总结 350
第15章  泛型 352
15.1  与C++的比较 352
15.2  简单泛型 353
15.2.1  一个元组类库 354
15.2.2  一个堆栈类 356
15.2.3  RandomList 357
15.3  泛型接口 358
15.4  泛型方法 361
15.4.1  杠杆利用类型参数推断 362
15.4.2  可变参数与泛型方法 363
15.4.3  用于Generator的泛型方法 364
15.4.4  一个通用的Generator 364
15.4.5  简化元组的使用 366
15.4.6  一个Set实用工具 367
15.5  匿名内部类 369
15.6  构建复杂模型 371
15.7  擦除的神秘之处 372
15.7.1  C++的方式 373
15.7.2  迁移兼容性 375
15.7.3  擦除的问题 376
15.7.4  边界处的动作 377
15.8  擦除的补偿 380
15.8.1  创建类型实例 381
15.8.2  泛型数组 383
15.9  边界 386
15.10  通配符 389
15.10.1  编译器有多聪明 391
15.10.2  逆变 393
15.10.3  无界通配符 395
15.10.4  捕获转换 399
15.11  问题 400
15.11.1  任何基本类型都不能作为类型
参数 400
15.11.2  实现参数化接口 401
15.11.3  转型和警告 402
15.11.4  重载 403
15.11.5  基类劫持了接口 404
15.12  自限定的类型 404
15.12.1  古怪的循环泛型 404
15.12.2  自限定 405
15.12.3  参数协变 407
15.13  动态类型安全 409
15.14  异常 410
15.15  混型 412
15.15.1  C++中的混型 412
15.15.2  与接口混合 413
15.15.3  使用装饰器模式 414
15.15.4  与动态代理混合 415
15.16  潜在类型机制 416
15.17  对缺乏潜在类型机制的补偿 420
15.17.1  反射 420
15.17.2  将一个方法应用于序列 421
15.17.3  当你并未碰巧拥有正确的
接口时 423
15.17.4  用适配器仿真潜在类型机制 424
15.18  将函数对象用作策略 426
15.19  总结:转型真的如此之糟吗? 430
15.19.1  进阶读物 432
第16章  数组 433
16.1  数组为什么特殊 433
16.2  数组是第一级对象 434
16.3  返回一个数组 436
16.4  多维数组 437
16.5  数组与泛型 440
16.6  创建测试数据 442
16.6.1  Arrays.fill() 442
16.6.2  数据生成器 443
16.6.3  从Generator中创建数组 447
16.7  Arrays实用功能 450
16.7.1  复制数组 450
16.7.2  数组的比较 451
16.7.3  数组元素的比较 452
16.7.4  数组排序 454
16.7.5  在已排序的数组中查找 455
16.8  总结 457
第17章  容器深入研究 459
17.1  完整的容器分类法 459
17.2  填充容器 460
17.2.1  一种Generator解决方案 460
17.2.2  Map生成器 462
17.2.3  使用Abstract类 464
17.3  Collection的功能方法 470
17.4  可选操作 472
17.4.1  未获支持的操作 473
17.5  List的功能方法 474
17.6  Set和存储顺序 477
17.6.1  SortedSet 479
17.7  队列 480
17.7.1  优先级队列 481
17.7.2  双向队列 482
17.8  理解Map 483
17.8.1  性能 484
17.8.2  SortedMap 486
17.8.3  LinkedHashMap 487
17.9  散列与散列码 488
17.9.1  理解hashCode() 490
17.9.2  为速度而散列 492
17.9.3  覆盖hashCode() 495
17.10  选择接口的不同实现 499
17.10.1  性能测试框架 499
17.10.2  对List的选择 502
17.10.3  微基准测试的危险 507
17.10.4  对Set的选择 508
17.10.5  对Map的选择 509
17.11  实用方法 512
17.11.1  List的排序和查询 514
17.11.2  设定Collection或Map为不可
修改 515
17.11.3  Collection或Map的同步控制 516
17.12  持有引用 518
17.12.1  WeakHashMap 519
17.13  Java 1.0/1.1 的容器 520
17.13.1  Vector 和 Enumeration 520
17.13.2  Hashtable 521
17.13.3  Stack 521
17.13.4  BitSet 522
17.14  总结 524
第18章  Java I/O系统 525
18.1  File类 525
18.1.1  目录列表器 525
18.1.2  目录实用工具 528
18.1.3  目录的检查及创建 532
18.2  输入和输出 533
18.2.1  InputStream类型 534
18.2.2  OutputStream类型 535
18.3  添加属性和有用的接口 535
18.3.1  通过FilterInputStream从
InputStream读取数据 535
18.3.2  通过FilterOutPutStream向
OutputStream写入 536
18.4  Reader和Writer 537
18.4.1  数据的来源和去处 537
18.4.2  更改流的行为 538
18.4.3  未发生变化的类 539
18.5  自我独立的类:RandomAccessFile 539
18.6  I/O流的典型使用方式 539
18.6.1  缓冲输入文件 540
18.6.2  从内存输入 540
18.6.3  格式化的内存输入 541
18.6.4  基本的文件输出 542
18.6.5  存储和恢复数据 543
18.6.6  读写随机访问文件 544
18.6.7  管道流 545
18.7  文件读写的实用工具 545
18.7.1  读取二进制文件 548
18.8  标准I/O 548
18.8.1  从标准输入中读取 548
18.8.2  将System.out转换成PrintWriter 549
18.8.3  标准I/O重定向 549
18.9  进程控制 550
18.10  新I/O 551
18.10.1  转换数据 554
18.10.2  获取基本类型 556
18.10.3  视图缓冲器 557
18.10.4  用缓冲器操纵数据 560
18.10.5  缓冲器的细节 560
18.10.6  内存映射文件 563
18.10.7  文件加锁 566
18.11  压缩 568
18.11.1  用GZIP进行简单压缩 568
18.11.2  用Zip进行多文件保存 569
18.11.3  Java档案文件 570
18.12  对象序列化 571
18.12.1  寻找类 574
18.12.2  序列化的控制 575
18.12.3  使用“持久性” 581
18.13  XML 586
18.14  Preferences 588
18.15  总结 589
第19章  枚举类型 590
19.1  基本enum特性 590
19.1.1  将静态导入用于enum 591
19.2  向enum中添加新方法 591
19.2.1  覆盖enum的方法 592
19.3  switch语句中的enum 593
19.4  values()的神秘之处 594
19.5  实现,而非继承 596
19.6  随机选取 596
19.7  使用接口组织枚举 597
19.8  使用EnumSet替代标志 600
19.9  使用EnumMap 602
19.10  常量相关的方法 603
19.10.1  使用enum的职责链 606
19.10.2  使用enum的状态机 609
19.11  多路分发 613
19.11.1  使用enum分发 615
19.11.2  使用常量相关的方法 616
19.11.3  使用EnumMap分发 618
19.11.4  使用二维数组 618
19.12  总结 619
第20章  注解 620
20.1  基本语法 620
20.1.1  定义注解 621
20.1.2  元注解 622
20.2  编写注解处理器 622
20.2.1  注解元素 623
20.2.2  默认值限制 624
20.2.3  生成外部文件 624
20.2.4  注解不支持继承 627
20.2.5  实现处理器 627
20.3  使用apt处理注解 629
20.4  将观察者模式用于apt 632
20.5  基于注解的单元测试 634
20.5.1  将@Unit用于泛型 641
20.5.2  不需要任何“套件” 642
20.5.3  实现@Unit 642
20.5.4  移除测试代码 647
20.6  总结 649
第21章  并发 650
21.1  并发的多面性 651
21.1.1  更快的执行 651
21.1.2  改进代码设计 653
21.2  基本的线程机制 653
21.2.1  定义任务 654
21.2.2  Thread类 655
21.2.3  使用Executor 656
21.2.4  从任务中产生返回值 658
21.2.5  休眠 659
21.2.6  优先级 660
21.2.7  让步 661
21.2.8  后台线程 662
21.2.9  编码的变体 665
21.2.10  术语 669
21.2.11  加入一个线程 669
21.2.12  创建有响应的用户界面 671
21.2.13  线程组 672
21.2.14  捕获异常 672
21.3  共享受限资源 674
21.3.1  不正确地访问资源 674
21.3.2  解决共享资源竞争 676
21.3.3  原子性与易变性 680
21.3.4  原子类 684
21.3.5  临界区 685
21.3.6  在其他对象上同步 689
21.3.7  线程本地存储 690
21.4  终结任务 691
21.4.1  装饰性花园 691
21.4.2  在阻塞时终结 694
21.4.3  中断 695
21.4.4  检查中断 701
21.5  线程之间的协作 702
21.5.1  wait()与notifyAll() 703
21.5.2  notify()与notifyAll() 707
21.5.3  生产者与消费者 709
21.5.4  生产者-消费者与队列 713
21.5.5  任务间使用管道进行输入/输出 717
21.6  死锁 718
21.7  新类库中的构件 722
21.7.1  CountDownLatch 722
21.7.2  CyclicBarrier 724
21.7.3  DelayQueue 726
21.7.4  PriorityBlockingQueue 728
21.7.5  使用ScheduledExecutor的温室
控制器 730
21.7.6  Semaphore 733
21.7.7  Exchanger 735
21.8  仿真 737
21.8.1  银行出纳员仿真 737
21.8.2  饭店仿真 741
21.8.3  分发工作 744
21.9  性能调优 748
21.9.1  比较各类互斥技术 748
21.9.2  免锁容器 754
21.9.3  乐观加锁 760
21.9.4  ReadWriteLock 761
21.10  活动对象 763
21.11  总结 766
21.11.1  进阶读物 767
第22章  图形化用户界面 768
22.1  applet 769
22.2  Swing基础 769
22.2.1  一个显示框架 771
22.3  创建按钮 772
22.4  捕获事件 773
22.5  文本区域 774
22.6  控制布局 776
22.6.1  BorderLayout 776
22.6.2  FlowLayout 776
22.6.3  GridLayout 777
22.6.4  GridBagLayout 777
22.6.5  绝对定位 778
22.6.6  BoxLayout 778
22.6.7  最好的方式是什么 778
22.7  Swing事件模型 778
22.7.1  事件与监听器的类型 779
22.7.2  跟踪多个事件 783
22.8  Swing组件一览 785
22.8.1  按钮 785
22.8.2  图标 787
22.8.3  工具提示 788
22.8.4  文本域 789
22.8.5  边框 790
22.8.6  一个迷你编辑器 791
22.8.7  复选框 792
22.8.8  单选按钮 793
22.8.9  组合框 793
22.8.10  列表框 794
22.8.11  页签面板 796
22.8.12  消息框 796
22.8.13  菜单 798
22.8.14  弹出式菜单 802
22.8.15  绘图 803
22.8.16  对话框 805
22.8.17  文件对话框 808
22.8.18  Swing组件上的HTML 809
22.8.19  滑块与进度条 810
22.8.20  选择外观 811
22.8.21  树、表格和剪贴板 812
22.9  JNLP与Java Web Start 812
22.10  Swing与并发 816
22.10.1  长期运行的任务 816
22.10.2  可视化线程机制 822
22.11  可视化编程与JavaBean 823
22.11.1  JavaBean是什么 824
22.11.2  使用Introspector抽取出
BeanInfo 825
22.11.3  一个更复杂的Bean 829
22.11.4  JavaBean与同步 831
22.11.5  把Bean打包 834
22.11.6  对Bean更高级的支持 835
22.11.7  有关Bean的其他读物 836
22.12  Swing的可替代选择 836
22.13  用Flex构建Flash Web客户端 836
22.13.1  Hello, Flex 837
22.13.2  编译MXML 838
22.13.3  MXML与ActionScript 838
22.13.4  容器与控制 839
22.13.5  效果与样式 840
22.13.6  事件 841
22.13.7  连接到Java 841
22.13.8  数据模型与数据绑定 843
22.13.9  构建和部署 843
22.14  创建SWT应用 844
22.14.1  安装SWT 845
22.14.2  Hello, SWT 845
22.14.3  根除冗余代码 847
22.14.4  菜单 848
22.14.5  页签面板、按钮和事件 849
22.14.6  图形 852
22.14.7  SWT中的并发 853
22.14.8  SWT还是Swing 855
22.15  总结 855
22.15.1  资源 855
附录A  补充材料 856
附录B  资源 859
索引 863

教学资源推荐
作者: 周纯杰 何顶新 周凯波 彭刚 张惕远 编著
作者: 刘奇志 尹存燕 曹迎春 编著
作者: (美)Ira Pohl
作者: Kathryn E.Sanders, Andries Van Dam
参考读物推荐
作者: (美)Aaftab Munshi,Benedict R. Gaster, Timothy G. Mattson, James Fung, Dan Ginsburg 著
作者: 丁如敏 王琳 等著
作者: [美]弗拉维奥·荣凯拉(Flavio Junqueira) 本杰明·里德(Benjamin Reed) 著