作者简介:Peter Haggar是IBM在北卡罗来纳州的Research Triangle Park的一名高级软件工程师,他发表了无数篇关于 Java 编程的文章。他有着广泛的编程经验,曾致力于开发工具、类库和操作系统的相关工作。Peter 在IBM从事新兴因特网技术方面的工作,目前主要从事有关高性能Web服务方面的工作。Peter经常在很多业界会议上作为技术发言人就 Java 技术发表言论。他已经为IBM工作了15年多,并获得了Clarkson University的计算机科学学士学位。
本书汇集了Java编程实践方面的建议、忠告、范例和讨论,本书的组织是一个个独立的课程,每个课程称为实践(PRAXIS),用以讨论特定主题,每个 实践按各自独立的方式撰写。本身详细分析了某些设计和编程方面的问题,挑选的依据是编程实践上的有效和高效。Java最被人抱怨的一点是性能,因此本书以 最大的篇幅讨论这一主题,使Java代码运行得更高效。
--------------------------------------------------------------------------------
General Techniques
PRAXIS1: 引数以by value方式而非by reference方式传递
所有Java对象都通过object reference被访问,常见的一个误解是java以by reference方式传递引数,
事实上所有引数都以by value方式传递。
比如int参数,在函数内修改了,在调用后并没有修改
而object则不是这样,函数内修改了,调用后也是修改的,若不想这样,可以把object改为不可变的或拷贝object
PRAXIS2: 对不变的data和object references使用final
为了让data或object reference成为不变量(常数),请使用final。注意,final仅仅令object reference
自身成为不变量,并不限制它所指对象的改变。
PRAXIS3: 缺省情况下所有non-static函数都可被覆盖
缺省情况下,所以non-static函数都可以被subclass覆盖,但如果加上关键字final,便可防止被subclass覆盖。
声明某个类为final,就表示这个类的所有函数都是final的,可以阻止它派生子类。
PRAXIS4: 在arrays和Vectors之间慎重选择
arrays 和vectors是常见的容器类(storage classes)。选用它们之前应该先了解它们的功用和特性。
如果超出了array的大小,会报数组越界异常,基本类型的array会自动为数组内的元素赋默认值,而对象数组则是null。而vector长度会自 动增长,vector.size()返回的元素的数量,不是固定值,vector的内部实现是array实现的,vector只能容纳对象。
一般来说,array速度更快。
PRAXIS5: 多态优于instanceof
instanceof 的许多用途可以因为改用多态而消失,使用多态,代码将更清晰、更易于扩展和维护。
PRAXIS6: 必要时才使用instanceof
有时我们无法回避使用instanceof。我们应该了解什么情况下必须使用它。
PRAXIS7: 一旦不再需要object references,就将它设为null
不要忽视内存可能带来的问题,尽管有了垃圾回收机制,你仍然需要关注你的代码如何运用内存,如果能够领悟垃圾回收和内存运用细节,你就能够更好的知道何时应该将object references设为null,那将导致高效的代码。
--------------------------------------------------------------------------------
Objects and Equality
PRAXIS8: 区分reference type和primitive type
Java 是面向对象语言,但其操控的东西并非都是对象(objects)。理解reference type和primitive types之间的差异,及它们在JVM中的表述,会使你在运用它们时得以做出明智的选择。
PRAXIS9: 区分==和equals()
== 用来测试基本型别的相等性,亦可判定两个object references是否指向同一个对象,但若要测试
values (值)或semantic(语义)相等,应使用equals()。
PRAXIS10: 不要依赖equals()的缺省实现
不要不假思索的认定一个class总是会正确的实现出equals(),此外,java.lang.Object提供的equals()大多数时候并非进行你想要的比较。
PRAXIS11: 实现equals()时必须深思熟虑
如果某个class所生的两个对象“即使不占用相同的内存空间,也被视为逻辑上相等”,那么就该为这个class提供一个equals()。
PRAXIS12: 实现equals()时优先考虑使用getClass()
实现equals()时请优先考虑采用getClass()。毕竟,“隶属同一个class下的对象才得被视为相等”是正确实现equals()的一个简明方案。
惟有相同class所产生的对象才可以被视为相等,可以只比较某些关键属性。
PRAXIS13: 调用super.equals()以唤起base class的相关行为
任何base class(除了java.lang.Object)如果实现equals(),其derived class都应该调用super.equals()。
PRAXIS14: 在equals()函数中谨慎使用instanceof
惟有当你考虑允许“一个derived class对象可以相等于其base class对象”时,才在equals()中使用instanceof。使用这项技术前请先弄清楚其影响。
PRAXIS15: 实现equals()时需遵循某些规则
撰写equals()并非那么直观,如果想要恰当实现出equals(),请遵循某些规则。
1. 如果某个class的两个对象即使占据不同的内存空间,也可被视为“逻辑上相等”的话,那么你得为这个class提供一个equals()。
2. 请检查是否等于this。
3. 比较这个class中的相关属性,以判断两个对象是否相等。
4. 如果有java.lang.Object以外的任何base class实现了equals(),那么就应该调用super.equals()。
--------------------------------------------------------------------------------
Exception Handling
PRAXIS16: 认识“异常控制流”(exception control flow)机制
了解异常控制流程细节,了解这些细微之处有助于你回避问题。
PRAXIS17: 不要忽略异常
一旦异常出现却没有被捕获,抛出异常的那个线程就会中止运行,是的,异常意味错误,永远不要忽略它。
PRAXIS18: 不要隐藏异常
如果处理异常期间又从catch或finally区段抛出异常,原先的异常会因而被隐藏起来,一旦发生这样的事情,就会丢失错误信息,你应当撰写专门负责处理这种情形的代码,将所有异常回传给调用者。
只有一个异常可以传播到外界,可以把所有的异常加入到一个vector内。
PRAXIS19: 理解throws子句的缺点
将一个异常加入某函数的throws子句,会影响该函数的所有调用者。
PRAXIS20: 细致而全面的理解throws子句
任何函数的throws子句应当列出它所传播的所有异常,包括衍生异常型别(derived exception types)。
//////////////////////////////////////////////////////////////////////
覆盖一个方法时,throws的异常受到约束
要么不抛出异常,要么和被覆盖方法一样类型的异常,要么是被覆盖方法异常的派生异常。
PRAXIS21: 使用finally避免资源泄漏
不要忽视内存以外的资源,垃圾回收机制不会替你释放它们,请使用finally确保内存以外的资源被释放。
PRAXIS22: 不要从try块中返回
不要从try区段中发出return语句,因为这个函数未必会立即从那儿返回,如果存在finally区段,它就会被运行起来并可能改变回传值。
PRAXIS23: 将try/catch代码块置于循环外
撰写含有异常处理的循环时,请将try和catch区段置于循环外部,在某些实现版本上,这会产生更快的运行代码。
PRAXIS24: 不要将异常用于流程控制
请将异常用于预期行为之外的情况,不要以异常来控制流程,请采用标准的语言流程构件,这样的流程表达会更清晰更高效。
PRAXIS25: 不要每逢出错就使用异常
只有面对程序行为可能出乎意料的情况下才使用异常,“预期中的行为”应使用返回代码来处理。
PRAXIS26: 在构造函数中抛出异常
尽管构造函数并非函数(method),因而不能回传一个值,但构造函数有可能失败,如果它们失败了,请抛出一个异常。
PRAXIS27: 抛出异常之前先将对象恢复为有效状态(valid state)
抛出异常很容易,困难的是“将异常所引发的伤害减到最小”,抛出异常前,应确保“如果异常被处理好,流程再次进入抛出异常的那个函数中,该函数可以成功完成”。
--------------------------------------------------------------------------------
Performance
PRAXIS28: 先把焦点放在设计、数据结构和算法身上
给java带来最大性能提升的办法就是:在设计和算法中使用与语言无关的技术,因此,首先请将你的精力集中在这上面。
PRAXIS29: 不要依赖编译期的优化技术
由java编译器生成的代码,通常不会比你自己撰写的更好,别指望编译器能够多么优化你的源码。
PRAXIS30: 理解运行期的代码优化技术
Java 对性能的大部分努力都围绕着“运行期优化”展开,这种做法有利无弊。
PRAXIS31: 如欲进行字符串的连接,StringBuffer优于String
对于字符串的连接,StringBuffer要比String快许多倍。
PRAXIS32: 将对象的创建成本降至最小
在许多面向对象系统中,“创建对象”意味着高昂的成本,了解成本所在,以及了解“加速对象创建速度”的技术,都可以导致更快速的程序。
PRAXIS33: 谨防未使用的对象
非必要别产生对象,否则会减慢你的程序速度。
PRAXIS34: 将同步(synchronization)减至最低
声明synchronized函数或synchronized区段,会显著降低性能,应该只在对象有所需要时才使用同步机制。
PRAXIS35: 尽可能使用stack变量
stack 变量为JVM提供了更高效的byte code指令序列,所以在循环内重复访问static变量或instance变量时,应当将它们暂时存储于stack变量中,以便获得更快的运行速度。
PRAXIS36: 使用static、final和private函数以促成inlining
以方法体替换方法调用,会导致更快速的程序,如果要令函数为inline,必须先声明它们为static、final或private。
PRAXIS37:instance 变量的初始化一次就好
由于所有static变量和instance变量都会自动获得缺省值,所以不必重新将它们设为缺省值。
PRAXIS38: 使用基本类型(primitive types)使代码更快更小
使用基本类型,比使用其包装类,产生的代码又小又快。
PRAXIS39: 不要使用Enumeration或Iterator来遍历Vector
遍历Vector时,请使用get()函数而非Enumeration或Iterator。这样做会导致更少的函数调用,意味程序速度更快。
PRAXIS40: 使用System.arraycopy()来复制arrays
这个是本机(native)函数,速度更快。
PRAXIS41: 优先使用array,然后才考虑Vector和ArrayList
如果你需要Vector的功能但不需要它的同步特性,可改用ArrayList。
PRAXIS42: 尽可能复用(reuse)对象
复用现有对象,几乎总是比创建新对象更划算。
PRAXIS43: 使用延迟求值(lazy evaluation)
如果某个成本高贵的计算并非一定必要,就尽量少做,使用懒加载技术避免那些永远不需要的工作。
PRAXIS44: 以手工方式将代码优化
由于Java编译器在优化方面的作为甚少,为了生成最佳byte code,请以手工方式将你的源码优化。
PRAXIS45: 编译为本机代码(native code)
编译为本机代码,通常可以获得运行速度更快的代码,但你却因此必须在各种不同的本机方案中取舍。
--------------------------------------------------------------------------------
Multithreading
PRAXIS46: 面对instance函数,synchronized锁定的是对象(object)而非函数(method)或代码
关键字synchronized锁定的是对象,而非函数或代码,一个函数或程序区段被声明为synchronized,并不意味同一时刻只能由一个线程运行它。
PRAXIS47: 弄清楚synchronized statics函数与synchronized instance函数之间的差异
两个函数被声明为synchronized,并不就意味它们是“多线程安全”,对instance函数或object reference同步化,与对static函数或class literal(字面常数)同步化相比,得到的lock全然不同。
PRAXIS48: 以private数据(field)+相应的访问函数(accessor)替换public/protected数据
如果没有适当保护你的数据,用户便有机会绕过你的同步机制。
PRAXIS49: 避免无谓的同步控制
一般情况下请不要同步化所有函数,同步化不仅造成程序缓慢,并且丧失了并发(concurrency)的可能,
请采用“单对象多锁”技术以允许更多并发动作。
PRAXIS50: 访问共享变量时请使用synchronized或volatile
不可切割(原子化,atomic)操作并非意味“多线程安全”,JVM实现品被允许在私有内存中保留变量的工作副本,这可能会产生陈旧数据,为避免这个问题,请使用同步化机制或将变量声明为volatile
PRAXIS51: 在单一操作中锁定所有用到的对象
同步化某一函数,并不一定就会使其成为“多线程安全”,如果synchronized函数操控着多个函数,而它们并不都是此函数所属class的private instance data,那么你必须对这些对象自身也进行同步化。
PRAXIS52: 以固定而全局性的顺序取得多个locks,以避免死锁(deadlock)
当你同步化多个对象,请以固定、全局性的顺序获得locks,以避免死锁。
PRAXIS53: 优先使用notifyAll()而非notify()
notify() 只唤醒一个线程,要想唤醒多个线程,请使用notifyAll()。
PRAXIS54: 针对wait()和notifyAll()使用旋锁(spin locks)
当你等待条件变量时,请总是使用旋锁确保正确结果。
PRAXIS55: 使用wait()和notifyAll()替换轮询循环(polling loops)
将所有polling loops替换为使用wait()、notify()和notifyAll()的spin locks(旋锁),spin locks直观而高效,polling loops则慢很多倍。
PRAXIS56: 不要对上锁对象(locked object)的object reference重新赋值
当一个对象被锁定,有可能其他线程会因同一个object lock而受阻(blocked),假如你对上锁对象的object reference重新赋值,其他线程内悬而未决的那些locks将不再有意义。
PRAXIS57: 不要调用stop()或suspend()
不要调用stop()或suspend(),因为它们可能导致数据内部混乱,甚至引发死锁。
PRAXIS58: 通过线程之间的协作来中止线程
你不应该调用stop(),如欲安全地停止线程,必须要求它们相互协作,才能姿态优雅的中止。
--------------------------------------------------------------------------------
Classes and Interfaces
PRAXIS59: 运用interfaces支持多重继承
当你想要支持interface的单一继承或多重继承,或想要实现一个标识型的interface时,请使用interfaces。
PRAXIS60: 避免interfaces中的函数发生冲突
没有任何办法能够阻止两个interfaces使用同名的常数和函数,为了避免可能的冲突,应当小心命名常数和函数。
PRAXIS61: 如需提供部分实现(partial implementation),请使用抽象类(abstract classes)
使用abstract class来为一个class提供部分实现,这些实现很可能对derived class是共通的。
PRAXIS62: 区分interface、abstract class和concrete class
一旦正确理解interface、abstract class和concrete class的差异,你就可以在设计是编码时做出正确的选择。
PRAXIS63: 谨慎定义和实现不可变类(immutable classes)
如果你希望对象内容永远不被改动,请使用不可变对象(immutable object),这种对象自动拥有“多线程安全性”。
PRAXIS64: 欲传递或接收可变对象(mutable objects)的object references时,请使用clone()
为了保证immutable objects,你必须在传入和回传它们时对它们施行clone()。
PRAXIS65: 使用继承或委托(delegation)来定义不可变类(immutable classes)
使用immutable interface、common interface或base class,或是immutable delegation classes,来定义immutable classes。
PRAXIS66: 实现clone()时记得调用super.clone()
当你实现一个clone(),总是应该调用super.clone()以确保产生正确的对象。
PRAXIS67: 别只依靠finalize()清理non-memory(内存之外)的资源
你不能保证finalize()是否被调用,以及何时被调用,因此,请专门实现一个public函数来释放内存以外的资源。
PRAXIS68: 在构造函数内调用non-final函数时要小心
如果一个non-final函数被某个derived class覆盖,在构造函数中调用这个函数可能会导致不可预期的结果
- 浏览: 463906 次
- 性别:
- 来自: 深圳
文章分类
最新评论
-
wwwjiandan:
我现在遇到的问题是将Activity设置为非全屏,且andro ...
Android中软键盘弹出时底部菜单上移问题 -
zjhdreams:
求下载链接
Android 9Patch (NinePatch) -
wtjandjay:
受教了 .......
从程序员到项目经理 -
mr_zhang2011:
将博客搬至CSDN -
fyc0109:
为什么我传过去的值, 有的都不对呢, 顺序也是一样的.就是获得 ...
Android Parcelable序列化自定义类集合在Activity间传递
发表评论
-
java集合Collection,Map及子类
2014-10-24 11:43 1044ArrayList Vector LinkedList ... -
清除Android工程中没用到的资源
2014-10-10 13:48 922清除Android工程中没用到的资源 项目需求一改再改, ... -
大型网站系统架构演化之路
2014-09-28 13:40 1210大型网站系统架构演 ... -
如何成为一名比逼格更逼格的java程序员
2014-09-28 10:25 802如何成为一名比逼格 ... -
操作系统原理简介
2014-09-26 15:45 918操作系统原理 我们 ... -
java集合
2013-12-17 10:13 858集合类说明及区别 Collection ├List │├Li ... -
java中的io系统详解
2013-12-17 10:11 704相关读书笔记、心得文章列表 http://blog.cs ... -
java io实践
2013-12-09 17:49 548java中的IO整理 http://www.cnblo ... -
TCP,UDP
2013-12-09 10:49 1077TCP/IP结构对应OSI OSI中的层 ... -
TCP, Scoket, HTTP
2013-12-09 10:37 8741、TCP连接 要想明白Soc ... -
Scoket:TCP通讯模型
2013-12-09 10:35 825Scoket:TCP通讯模型 Socket编程模型是 ... -
final类,方法,变量
2013-07-12 17:46 805见附件: -
在父类获取子类属性
2012-05-11 18:13 2353在父类获取子类属性 在父类中能获取子类的属性吗?一般情况 ... -
java Collection与Map简介
2011-11-29 11:09 1085ArrayList 和Vector是采用数组方式存储 数据, ... -
JAVA 注解---积累
2011-07-27 12:00 1223转载http://www.iteye.com/topic/40 ... -
List的有用实现 1.ArrayList 2.LinkedList 3.Vector 4.Stack
2011-07-06 22:56 1564* * * List的有用实现 ... -
String a = new String("xyz");到底是几个对象?
2011-07-06 22:26 1301String a = new String("xyz ... -
java垃圾收集机制
2011-05-17 22:12 10461.垃圾收集算法的核心 ... -
Java 内存管理原理、内存泄漏实例及解决方案
2011-05-17 21:47 957在项目的最后阶段,就是要防止系统的内存泄漏了,顺便找了些资料 ... -
Java对象的强,软,弱和虚引用
2011-05-17 17:36 997在JDK1.2以前的版本中,当一个对象不被任何变量引用, ...
相关推荐
《Practical Java》是侯捷老师的一本关于Java编程实践的书籍,旨在帮助读者深入理解Java语言,并通过实际代码示例提升编程技能。这本书涵盖了Java的基础到进阶内容,是学习和提升Java技术的重要资源。 1. **Java...
《Practical Java》和《Effective Java》正是这样两部著作,它们对Java的重要而基础的技术细节进行了详尽、深刻的介绍和剖析,每个主题独立成章,既方便读者根据需求选择性阅读,又能彼此呼应,形成一个完整的学习...
《Practical Java全书源码》是一份宝贵的资源,它涵盖了J2ME(Java 2 Micro Edition)平台上的手机游戏开发。J2ME是Oracle公司为小型设备和嵌入式系统设计的一种Java平台,广泛应用于早期的移动设备,如功能手机和...
《实用Java编程(含源码)》是一本专注于解决Java编程实际问题的书籍,它针对的是Java程序员在日常开发过程中可能会遇到的各种困扰和难题。这本书的目的是为了解答那些经常出现但又容易让人迷惑的问题,从而提升Java...
《实用Java(中文版)》是一本由资深Java编程专家撰写的指南,旨在提供实际、高效且具有针对性的Java编程实践经验。这本书经过侯捷的翻译,确保了内容的准确性和可读性,对于中文读者来说,是学习和提升Java技能的...
Practical Java viii 2 對象與相等性(Objects and Equality) 25 實踐8:區分reference type 和primitive type 25 實踐9:區分== 和 equals() 29 實踐10:不要倚賴equals()的缺省實現33 實踐11:實現equals()時必須...
《Practical Java》中文版随书源码是一个包含与J2ME手机游戏开发相关的实践教程资源。这本书通过实例深入浅出地介绍了Java编程语言在移动平台上的应用,特别是针对Java Micro Edition (J2ME)环境。J2ME是Java的一个...
侯捷和刘永丹合译得Practical Java,压缩包内含3个文件,其中2个pdf,一个为全简体版,虽有所删割,我还没添加书签,但排版良好,推荐。 另一个是网友合成版,前3章是侯捷发布的免费版,当然是繁体的,后面的是网上...
《Practical Java》是由著名程序员侯捷编写的关于Java编程实践的一部著作,该书深入浅出地探讨了Java编程的各个方面,旨在帮助开发者提升实际编程能力。在压缩包"practical_java.zip"中,包含了两个主要文件:...
### 实践1:Java中的参数传递机制 #### 参数传递方式:值传递 vs 引用传递 在Java中,参数是以**值传递**(by value)的方式传递给方法的,而不是很多人误解的**引用传递**(by reference)。这种误解往往来源于Java...
《Practical Java》是一本由资深Java专家编写的实践性指南,旨在帮助读者深入理解Java编程语言,并提供改进代码质量的实用策略。这本书的核心在于68个关键主题,每个主题都针对一个特定的编程问题或最佳实践,旨在...
《Practical Java》是Java编程领域的一部经典之作,作者为(美)海格尔,它与《Effective Java》齐名,都是程序员提升编程技能的重要参考资料。本书深入浅出地介绍了如何编写高质量、高效的Java程序,旨在帮助开发者...
Practical Java Game Programming Chapter 1 - Java as a Game Platform Chapter 2 - Fundamentals of Game Programming Chapter 3 - 2D Graphics Programming Chapter 4 - Creating Game Audio Using Java...
Deep Learning: Practical Neural Networks with Java by Yusuke Sugomori English | 8 Jun. 2017 | ASIN: B071GC77N9 | 1057 Pages | AZW3 | 20.28 MB Build and run intelligent applications by leveraging key ...
《Practical Java》是Java编程领域的一本经典教程,由著名技术翻译家侯捷先生翻译。这本书深入浅出地介绍了Java编程语言的核心概念和技术,旨在帮助读者从实践角度理解和掌握Java编程。书中涵盖的内容广泛,从基本...
本资源“Practical Java Source Code”旨在提供一系列实际应用中的Java代码示例,帮助开发者深入理解Java编程的实践操作。 Java的核心特性包括面向对象、平台独立性(通过Java虚拟机JVM实现)、丰富的类库、强大的...
《Java实用指南》是针对Java编程语言的一本实践性很强的参考书籍,旨在帮助开发者深入理解和熟练运用Java技术。这个RAR压缩包包含了该书的.chm格式电子版,方便读者在计算机上查阅和学习。 Java作为一种广泛使用的...