Practical Java中文版

Practical Java中文版
作 者: Peter Haggar 侯捷 刘永丹
出版社: 中国电力出版社
丛编项: 开发大师系列
版权说明: 本书为出版图书,暂不支持在线阅读,请支持正版图书
标 签: Java
ISBN 出版时间 包装 开本 页数 字数
未知 暂无 暂无 未知 0 暂无

作者简介

  Peter Haggar是一位公认的Java编程专家,也是IBM资深软件工程师。他拥有广博的编程经验,曾投身于开发工具、类库(class libraries)和操作系统的方面工作。他在IMB致力于emerging Java技术研究,目前专门从事embedded Java和real-time Java的研究。Peter屡屡以Java技术演讲人的身份出现在众多企业界会议上。他在Clarkson大学得计算机学士学位。

内容简介

本书出自第一线Java编程专家之手,为读者展现正确、高效、强国之JAVA代码实践方案。这本取材广泛的指南,以不同层级的专家经验,帮助程序员更透彻地理解JAVA,使他们的编码效能(coding effectiveness)发挥到极致。此书以准则/条款形式(rules-based)进行编排,探究改善代码的68个重要主题,提供清晰明快、精心撰写之示例和方案。所有示例和方案都带有详尽的解说,你可以将它们融入自身工作之中。这些编程和设计上的实践方案,描述了经验丰富的程序员实际运用之最佳实践手法。为方便中高阶JAVA程序员阅读,本书内容被精心安排成为各自独立的课程,因此你既可以从头通读至尾,也可以挑选独特专题加以精读。

图书目录

实践:实际履行, 尤指艺术. 科学或技术领域:与理论遥相对应.

Praxis: Practice,especially of an art,science, or technical occupation, opposite to theory.

-Webster''s New Collegiate Dictionary 1958

译序by侯捷

译序by刘永丹

细目 DetailContents

前言preface

致谢 Acknowledgement

1 一般技术(General Techniques)

实践1:参数以byvalue方式而非by reference方式传递

实践2:对不变的data和object reference使用final

实践3:缺省情况下所有non-static函数都可被覆写

实践4:在arrays和vectors之间慎重选择

实践5:多态 po1ymorphism 优于instanceof

实践6:必要时才使用instanceof

实践7:一旦不再需要objectreferences, 就将它设为nu11

2 对象与相等性(Objects and Equality)

实践8:区分reference型别和primitive型别

实践9:区分==和equals

实践10:不要依赖equals 的缺省实现

实践11:实现equals 时必须深思熟虑

实践12:实现equals 时优先考虑使用getClass

实践13:调用super. equals 以唤起baseclass的相关行为

实践14:在equals 函数中谨慎使用instanceof

实践15:实现equals 时需遵循某些规则

3异常处理(Exception Handling)

实践16:认识[异常控制流] exceptioncontrolflow 机制

实践17:绝对不可轻忽异常 Neverignoreanexception

实践18:千万不要遮掩异常 Neverhideanexception

实践19:明察throws子句的缺点

实践20:细致而全面地理解throws子句

实践21:使用finally避免资源泄漏 resourceleaks

实践22:不要从try区段中返回

实践23:将try/catch区段置于循环之外

实践24:不要将异常 exceptions 用于流程控制

实践25:不要每逢出错就使用异常 exceptions

实践26:在构造函数 constructors 中抛出异常

实践27:抛出异常之前先将对象恢复为有效状态 valid state

4 性能(Performance)

实践28:先把焦点放在设计. 数据结构和算法身上

实践29:不要倚赖编译期 compile-time 优化技术

实践30:理解运行期 mntime 代码优化技术

实践31:如欲进行字符串接合, StringBuffer优于String

实践32:将对象的创建成本 creationcost 降至最小

实践33:慎防未用上的对象 unusedobjects

实践34:将同步化 synchronization 降至最低

实践35:尽可能使用stack变量

实践36: 使用static. final和private函数以促成inlining

实践37:instance变量的初始化一次就好

实践38:使用基本型别 primitivetypes 使代码更快更小

实践39:不要使用Enumeration或Iterator来遍历vector

实践40:使用System. arraycopy 来复制arrays

实践41:优先使用array, 然后才考虑Vector和ArrayList

实践42:尽可能复用 reuse 对象

实践43:使用缓式评估 延迟求值, lazyevaluation

实践44:以手工方式将代码优化

实践45:编译为本机代码 Compile to native code

5 多线程 Multithreading

实践46:面对instance函数, synchronized锁定的是对象 objects 而非函数 methods 或代码 code

实践47:弄清楚synchronizedstatics函数与synchronized instance函数之间的差异

实践48:以[private数据十相应访问函数 accessor ]替换[public/protected数据]

实践49:避免无谓的同步控制

实践50:访问共享变量时请使用synchronized或volatile

实践51:在单一操作 singleoperation 中锁定所有用到的对象

实践52:以固定而全局性的顺序取得多个locks 机锁 以避免死锁

实践53:优先使用notifyAll 而非notify

实践54:针对wait 和notifyAll 使用旋锁 spinlocks

实践55:使用wait 和notifyAll 替换轮询循环 pollingloops

实践56:不要对locked object 上锁对象 之object reference重新赋值

实践57:不要调用stop 或suspend

实践58:通过线程 threads 之间的协作来中止线程

6 类与接口(Classes and Interfaces)

实践59:运用interfaces支持多重继承 multipleinheritance

实践60:避免interfaces中的函数发生冲突

实践61:如需提供部分实现 partial implementation 请使用abstract classes 抽象类

实践62:区分interface. abstractclass和concreteclass

实践63:审慎地定义和实现immutableclasses 不可变类

实践64:欲传递或接收mutableobjects 可变对象 之objectreferences时, 请实施clone

实践65:使用继承 inheritance 或委托 delegation 来定义immutableclasses 不可变类

实践66: 实现clone 时记得调用super. clone

实践67:别只依赖finalize 清理non-memory 内存以外 的资源

实践68:在构造函数内调用non-final函数时要当心

附录:如何学习Java

进阶读物 Further Reading

索引 Index

一般技术(General Techniques)

实践1:引数是以传值(by value)而非传址(by reference)方式传递

所有Java objects都透过object reference而被取用. 常见的一个误解是Java以by reference方式传递引数. 事实上所有引数都以by value方式传递.

实践2:对不变的data和object reference使用final

为了让data或object reference成为不变量, 请使用final. 注意, final仅仅令object reference自身成为不变量, 并不限制它所指向之物件的改变.

实践3:预设情况下所有non-static函式都可被覆写(overridden)

预设情况下, 所有non-static函式都可以被subclass覆写. 但如果加上关键字final, 便可防止被subclass覆写.

实践4:慎重选择arrays和Vectors

arrays和vectors是常见的容器类别(storage classes). 选用它们之前应该先了解它们的功用和特性.

实践5:多型(polymorphism)优於instanceof

instanceof的许多用途可以因为改用多型而消除之. 使用多型, 程式码将更清晰. 更易於扩展和维护.

实践6:必要时才使用instanceof

有时我们无法回避使用instanceof. 我们应该了解什麽情况下必须使用它.

实践7:一旦不再需要object references, 就将它设为null

不要忽视记忆体可能带来的问题. 尽管有了垃圾回收机制(garbage collection), 你仍然需要关注你的程式码如何运用记忆体. 如果能够领悟垃圾回收机制和记忆体运用细节, 你就能够更好地知道何时应该将object references设为null, 那将导致高效的程式码.

物件与相等性(Objects and Equality)

实践8:区分reference type和primitive type

Java是物件导向的, 但其操控的东西并非都是物件(objects). 理解reference type和primitive types之间的差异, 及它们在JVM中的表述(representation), 会使你在运用它们时得以做出明智的选择.

实践9:区分 == 和equals

== 用来测试基本型别的相等性, 亦可判定两个object references是否指向同一个object. 若要测试values(值)或semantic(语意)相等, 应使用equals .

实践10:不要依赖equals 的预设实作(default implementation)

不要不假思索地认定一个class总是会正确实作出equals . 此外, java.lang.Object提供的equals 大多数时候并非进行你想要的比较.

实践11:实作equals 时必须深思熟虑

如果某个class的两个objects「即使不占用相同的记忆体空间, 也被视为逻辑上相等」, 那麽就该为这个class提供一个equals .

实践12:实作equals 时优先考虑使用getClass

实作equals 时请优先考虑采用getClass . 毕竟, 「相同class下的objects才得被视为相等」是正确实作equals 的一个清晰简明的解决方案.

实践13:呼叫base class(基础类别)的super.equals

任何base class(除了java.lang.Object)如果实作equals , 其derived class都应该呼叫super.equals .

实践14:在equals 函式中谨慎使用instanceof

唯有当你考虑允许「一个derived class object可以相等於其base class object」时, 才在equals 中使用instanceof. 使用这项技术前请先弄清楚其影响.

实践15:实作equals 时需遵循某些规则

撰写equals 并非那麽直观浅白. 如果想要恰当地实作出equals , 请遵循某些规则.

异常处理(Exception Handling)

实践16:认识「异常控制流」(exception control flow)机制

让自己谙晓异常控制流程细节. 了解这些细微之处有助於你回避问题.

实践17:绝对不可轻忽异常(Never ignore an Exceptions)

一旦异常出现却没有被捕获, 抛出异常的那个执行绪(thread)就会中止运行. 是的, 异常意味错误, 永远不要忽略它.

实践18:千万不要掩盖异常(Never hide an Exceptions)

如果处理异常期间又从catch或finally区段抛出异常, 原先的异常会因而被隐蔽起来. 一旦发生这样的事情, 就会丢失错误资讯. 你应当撰写专门负责处理这种情形的程式码, 将所有异常回传给呼叫者.

实践19:明察throws子句的缺点

将一个异常加入某函式的throws子句, 会影响该函式的所有呼叫者.

实践20:细致而全面地理解throws子句

任何函式的throws子句应当列出它所传播的所有异常, 包括衍生异常型别(derived exception types).

实践21:使用finally避免资源泄漏(resource leaks)

不要忽视记忆体以外的资源. 垃圾回收机制不会替你释放它们. 请使用finally确保记忆体以外的资源被释放.

实践22:不要从try区块中回返

不要从try区块中发出return指令, 因为这个函式未必会立即从那儿回返. 如果存在finally区段, 它就会被执行起来并可能改变回传值.

实践23:将try/catch区块置於回圈(loop)之外

撰写含有异常处理的回圈时, 请将try和catch区块置於回圈外部. 在某些实作版本上, 这会产生更快的执行码.

实践24:不要将异常(exceptions)用於流程控制

请将异常用於预期行为之外的情况. 不要以异常来控制流程, 请采用标准的语言流程构件(flow constructs), 这样的流程表达会更清晰更高效.

实践25:不要每逢出错就使用异常(exceptions)

只有面对程式行为可能出乎预料的情境下才使用异常. 「预期中的行为」应使用回传码(return codes)来处理.

实践26:在建构式(constructors)中抛出异常

尽管建构式并非函式(method), 因而不能回传一个值, 但建构式有可能失败. 如果它们失败了, 请抛出一个异常.

实践27:抛出异常(exceptions)之前先将object恢复为有效状态

抛出异常很容易, 困难的是「将异常所引发的伤害减到最小」. 抛出异常之前, 应确保「如果异常被处理好, 流程再次进入抛出异常的那个函式中, 该函式可以成功完成」.

效能/效率(Performance)

实践28:先把焦点放在设计. 资料结构和演算法身上

给Java带来最大效能提升的办法就是:在设计和演算法中使用与语言无关的技术. 因此, 首先请将你的精力集中於这些上面.

实践29:不要倚赖编译期程式码优化技术

由Java编译器生成的码, 通常不会比你自己撰写的更好. 别指望编译器能够多麽优化你的原始码.

实践30:理解运行期(runtime)程式码优化技术

Java效能的大部分努力都围绕着运行期优化展开. 这种作法有利有弊.

实践31:如欲进行字串接合, StringBuffer优於String

对於字串接合, StringBuffer class要比String class快许多倍.

实践32:将object的创建成本(creation cost)降至最小

在许多物件导向系统中, 「产生物件」意味着高昂的成本. 了解成本所在, 以及了解「加速物件产生速度」的技术, 都可以导致更快的程式码.

实践33:慎防未用上的物件(unused objects)

非必要别产生物件. 非必要地产生物件, 会减慢你的程式速度.

实践34:将同步(synchronization)减至最低

宣告synchronized函式或synchronized区块, 会显着降低效能. 只在物件需要时才使用同步机制(synchronization).

实践35:尽可能使用stack变数

stack变数为JVM提供了更高效的byte code指令序列. 所以在回圈内重复取用static变数或instance变数时, 应当将它们临时储存於stack变数中, 以便获得更快的执行速度.

实践36:使用static. final和private函式以允许实施inlining

以函式本体替换函式呼叫, 会导致更快的程式码. 如果要令函式为inline, 必须先宣告它们为static. final或private.

实践37:instance变数的初始化只要一次就好

由於所有static变数和instance变数都会自动获得预设值, 所以不必重新将它们设为预设值.

实践38:使用基本型别(primitive types)使程式码更快更小

使用基本型别, 比使用基本型别外覆类别(wrapper), 产生的程式码又小又快.

实践39:不要使用Enumeration或Iterator来巡访Vector

巡访Vector时, 请使用get函式而非Enumeration或Iterator. 这样做会导致更少的函式呼叫, 意味程式码会更快.

实践40:使用System.arraycopy

来复制arrays

请使用System.arraycopy

来复制arrays. 那是个原生(native)函式, 速度最快.

实践41:优先使用array, 然後才考虑Vector和ArrayList

如果可能, 就使用array. 如果你需要Vector的功能但不需要它的同步特性, 可改用ArrayList.

实践42:尽可能复用(reuse)objects

复用现有物件, 几乎总是比产生新物件更划算.

实践43:使用缓式评估(延迟求值, lazy evaluation)

如果某个成本高贵的计算并非一定必要, 就尽量少做. 请使用「缓式评估」

(lazy evaluation, 延迟求值)技术避免那些永远不需要的工作.

实践44:手工优化(optimize)你的程式码

由於Java编译器在优化方面的作为甚少, 为了生成最佳byte code, 请手工优化你的原始码.

实践45:编译为原生码(native code)

编译为原生码, 通常可以导致执行速度更快的程式码. 但你却因此必须在各种不同的原生方案(native solution)中取舍.

多绪(Multithreading)

实践46:面对instance函式, synchronized锁定的是物件而非函式或程式码

关键字synchronized锁定的是物件, 而非函式或程式码. 一个函式或程式

区段被宣告为synchronized, 并不意味同一时刻只能由一个执行绪执行它.

实践47:弄清楚synchronized statics与synchronized instance函式之间的差异

两个函式被宣告为synchronized, 并不就意味它们是「执行绪安全」(thread-safe)的. 对instance函式或object reference同步化, 与对static函式或class literal(字面常数)同步化相比, 得到的lock全然不同

实践48:以「private资料搭配存取器(accessor)」取代public/protected资料

如果没有适当保护你的资料, 用户便有机会绕过你的同步机制.

实践49:避免无谓的同步控制(avoid unnecessary synchronization)

一般情况下请不要同步化所有函式. 同步化不仅造成程式缓慢, 并且丧失了

并行(concurrency)的可能. 请采用「单物件多锁」技术以允许更多并行.

实践50:取用共享变数时请使用synchronized或volatile

不可切割(原子化, atomic)操作并非意味「执行绪安全」. JVM实作品被允许在私有记忆体中保留变数的工作副本. 这可能会产生陈旧数值(stale values). 为避免这个问题, 请使用同步化机制或将变数宣告为volatile.

实践51:在单一操作(single operation)中锁定所有用到的objects

同步化某一函式, 并不一定就会使其成为「执行绪安全」的函式码. 如果synchronized函式操控着多个objects, 而它们并不都是此函式所属class的private instance data, 那麽你必须对这些objects自身也进行同步化.

实践52:以固定而全域性的顺序取得多个locks(机锁)以避免死结(deadlock)

当你同步化多个物件, 请以固定和全域性的顺序获得locks, 以避免死结.

实践53:优先使用notifyAll 而非notify

notify 只唤醒一个执行绪. 要想唤醒多个执行绪, 请使用notifyAll .

实践54:针对wait 和notifyAll 使用旋锁(spin locks)

当你等待条件变数(condition variables)时, 请总是使用旋锁(spin locks)以确保正确结果.

实践55:使用wait 和notifyAll 取代轮询回圈(polling loops)

将所有polling loops替换为使用wait . notify 和notifyAll 的spin locks(旋锁). 使用spin locks直观而高效, 使用polling loops则慢很多倍.

实践56:不要对locked object(上锁物件)之object reference重新赋值

当一个object被锁定, 有可能其他执行绪会因同一个object lock而受阻(blocked). 假如你对上锁物件的object reference重新赋值, 其他执行绪中悬而未决的那些locks将不再有意义.

实践57:不要呼叫stop 或suspend

不要呼叫stop 或suspend , 因为它们可能导致资料内部混乱, 甚至引发死结(deadlock).

实践58:透过执行绪(threads)之间的合作来中止执行绪

你不应该呼叫stop . 如欲安全地停止执行绪, 必须要求它们相互协作, 才能姿态优雅地中止.

类别与介面(Classes and Interfaces)

实践59:使用interface支援多重继承(multiple inheritance)

当你想要支援interface的单一继承或多重继承, 或者想要实作一个标记式的(marker)interface时, 请使用interfaces.

实践60:避免interfaces中的函式发生冲突

没有任何办法能够阻止两个interfaces使用同名的常数和函式. 为了避免可能的冲突, 应当小心命名常数和函式.

实践61:需要提供部分实作(partial implementation)时, 请使用abstract classes

使用abstract class来为一个class提供部分实作, 这些实作很可能对derived class是共通的(都被需要的).

实践62:区分interface. abstract class和concrete class

一旦正确理解了interface. abstract class和concrete class的差异, 你就可以在设计和撰码时做出正确的选择.

实践63:审慎地定义和实作immutable classes(恒常类别)

如果你希望object的资料永远不被改动, 请使用immutable object. 这种objects自动拥有执行绪安全性(thread safety).

实践64:欲传递或接收mutable objects(可变物件)之object references时, 请施行clone

为了保证immutable objects, 你必须在传入和回传immutable objects时对它们进行clone动作.

实践65:使用继承(inheritance)或委托(delegation)来定义 immutable classes(恒常类别)

使用immutable interface. common interface或base class, 或是immutable delegation classes, 来定义immutable classes(恒常类别).

实践66:实作clone 时记得呼叫super.clone

当你实作了一个clone , 总是应该呼叫super.clone 以确保产生正确的object.

实践67:别只是倚赖finalize 清理记忆体以外的(non-memory)资源

你不能保证finalize 是否被呼叫, 以及何时被呼叫. 因此, 请专门实作一个public函式来释放记忆体以外的资源.

实践68:在建构式(constructors)内呼叫non-final函式时要当心

如果一个non-final函式被某个derived class覆写, 在建构式中呼叫这个函式可能会导致不可预期的结果.