【《Effective Java》学习笔记】
文章平均质量分 93
TonyLian
这个作者很懒,什么都没留下…
展开
-
【第48条】对共享可变数据的同步访问
《第9章 线 程》 通过使用线程(thread)可以在同一程序中同时进行多个活动。多线程程序设计比单线程程序设计要困难得多。所以如果一个类库可以帮助你从低层的多线程程序设计中解脱出来,那么一定要使用这个类。即使这样,有时候仍然要编写或者维护多线程代码,所以本章包含的建议可以帮助我们写出清晰、正确、文档组织良好的多线程程序。 【第48条】对共享可变数据的同步访问 &l...2009-06-23 12:18:18 · 212 阅读 · 0 评论 -
【第35条】接口优于映像机制
我个人更觉得,“映像机制”翻译为“反射机制”应该更好一些。反射是Java中的一个重要特性,给定一个字符串的类名称,可以得到这个类的一个实例、构造函数、公有的域和方法,并可调用这些方法。这种通过类名称反向等到类的实例和具体信息的能力,给Java带来了很多强大的功能,但同时也会带来不安定因素。 如果使用反射机制,就意味着:● 损失了编译时类型检查的好处● 要求执行反射的...2009-05-31 15:18:31 · 108 阅读 · 0 评论 -
【第34条】通过接口引用对象
在【第25条】中已经讲过“应该使用接口,而不是类作为参数的类型”。更进一步地讲,应该优先使用接口而不是类来引用对象。也就是说,当我们在考虑引入一个引用变量的时候,应该首先考虑的是,我们需要一个具有什么样功能的变量,也就是选择一个什么接口。之后才是在众多的实现类中选择一个合适的实现进行初始化。 // Interface object = new Class(); Map myTable ...2009-05-31 15:04:31 · 134 阅读 · 0 评论 -
【第33条】了解字符串连接的性能
这一条是一个良好的“习惯”,你可能一直没有注意到,但也没出什么问题,但是学会这一条会有不少性能的提高。 两个字符串连接,一般是通过 + 操作符进行的。如 String s = "a" + "b";String str = "Hello: ";str = str + someone.getName().toString(); 但是,由于...2009-05-27 15:58:42 · 182 阅读 · 0 评论 -
【第32条】如果其他类型更合适,请尽量避免使用字符串
这两天在研究通过Hessian远程连接Java和C#。功能强大而稳定,有着跨平台、集群化优势的Java,就像勤劳勇敢的“牛郎”;极具用户亲和力与体验感、天生与Office系列有着良好关系的.Net,就像美貌的“织女”,这样的强强联手是多么美好呀!但是,只是用户和我们这些人觉得美好,人家MS就不觉得美好。以至于如此有生命力的组合,至今还是隔着银河,很难牵手。Hessian是个好东西(最近国人的PHP...2009-05-27 15:40:54 · 130 阅读 · 0 评论 -
【第29条】将局部变量的作用域最小化
《第7章 通用程序设计》 本章主要讨论Java语言的语法细节。和上一章类似,很多条目都同样适用于其他面向对象的开发语言,尤其是类C语言们。 【第29条】将局部变量的作用域最小化 将局部变量的作用域最小化,可以增加代码的可读性和可维护性,并降低出错的可能性。C语言要求局部变量必须声明在代码块的开始处,出于习惯很多人依然这样做。但是现在应该打破这一习惯了。为了使局...2009-05-25 17:33:48 · 286 阅读 · 4 评论 -
【第31条】如果要求精确的答案,请避免使用float和double
float和double型,的底层实现是二进制的。十进制中的一个有限位数小数,转换成二进制就不一定是有限位数了,一旦位数超过的float和double型的位数宽度,就会出现“精度溢出”。所以float和double型是为了科学计算而设计的,并不适合精确的十进制计算,尤其不适合用来表示货币。 我以前也曾出货类似于为什么 2.0f - 1.9f 的结果不是 0.1f 之类的面试题...2009-05-25 16:30:14 · 129 阅读 · 0 评论 -
【第30条】了解和使用库
Java语言的丰富多彩,很大程度上是体现在丰富的类库上的。加之其开源,不计其数的各种第三方包就更不胜枚举。面对这些前人的财富,我们没有理由“装看不见”,而一定是要为我所用的。 第三方包姑且不论,只说JDK中的类库,我们应该掌握。只是到知道都有哪些功能的地步,用的时候可以再细查文档。最怕那些“乃不知有汉”的程序员。 还有一种程序员并非“乃不知有汉”型,而是无视...2009-05-25 15:46:00 · 149 阅读 · 0 评论 -
【第28条】为所有导出的API元素编写文档注释
Javadoc真是个好东西。它简直太奇妙了,简直就是“懒人乐”。 其实,不仅仅是受“懒人”欢迎,它还有标准化、一元化等其他好处... 那么,懒人们可听好了:为了正确地编写API文档,你必须在每一个被导出的类、接口、构造函数、方法和域声明之前加上文档注释。每一个方法的文档注释应该简洁地描述出它和使用者之间的约定。 具体的@语法,这里就不介绍了。...2009-05-22 14:22:53 · 120 阅读 · 0 评论 -
【第27条】返回零长度的数组而不是null
这一条从题目上即可了解几乎所有信息。虽然简单的没有什么可说的,但它真的非常让我“吃惊”。是呀,这么简单的道理怎么之前从没想过?为什么翻开我的代码,return null; 遍地开花!? 如果非要解释一下原因,那只有一句话:避免给调用者带来过的的保护性检查的麻烦。 那么,我们能否接着推论一下呢? —— 返回一个新new的实例,而不是null。如果从“避免给调用者带来...2009-05-22 14:12:06 · 118 阅读 · 0 评论 -
【第26条】谨慎地使用重载
重载是OO的一个重要特性,然而过度的重载只会带来更多的麻烦。书中一上来就举了一个通过超类与子类类型的参数来重载的例子。 当我们希望根据传入参数的类型来选择重载方法时,由于Java对重载方法的选择是静态的,所以尽量避免通过有继承关系的不同类型来重载。如果一个方法的参数类型(以仅有一个参数为例)是String,而另一个重载的参数类型是int,这样是安全的。而一个是List,另一...2009-05-22 13:59:07 · 129 阅读 · 0 评论 -
【第36条】谨慎地使用本地方法
Java Native Interface(JNI,Java本地接口),可以调用本地方法。这里的“本地”是指用其他语言(如 C, C++) 编写的特殊方法。 从历史上看,使用JNI主要有三个用途: 1)由于Java程序是运行在虚拟机之上的,虚拟机作为中间件,带来的平台无关性的好处的同时,也使得那些要求访问OS甚至硬件的底层操作变得无所适从。通过JNI可以调用C/C+...2009-06-03 15:50:52 · 177 阅读 · 0 评论 -
【第37条】谨慎地进行优化
这一条我没有什么好评价的,记住作者的忠告就好。 作者的意思大概有三点吧:1)任何优化都存在风险,有时候弄不好反而带来其他的问题 2)并不是 性能 优先。努力编写好的程序而不是快的程序。 3)对前人,尤其是类似于Java API这样的成熟代码,进行优化,是不明智的(要是能优化,人家早就做了) 其实,不仅仅是优化。随着项目的进展,尤其是到了后...2009-06-03 15:57:33 · 162 阅读 · 0 评论 -
【第47条】不要忽略异常
作为本章的最后一条,此条目是一条“纪律”,一条你必须遵守的纪律。虽然这是显而易见的道理,但却很容易被违反。 任何一个被抛出的异常都是API设计者有意为之的,其中蕴含了特定的含义,所以千万不能忽略它们! try{ ......}catch (Exception e){} 这样的代码并不十分罕见,这有可能是在代码堆砌阶段的“简...原创 2009-06-15 11:51:26 · 183 阅读 · 0 评论 -
【第46条】努力使失败保持原子性
所谓失败的原子性,就是在一个方法失败之后,使对象保持“它在被调用之前的状态”。因为,尤其是CheckedException发生后,一般是希望程序可以从异常中恢复过来的。 那么如何才能保持对象的状态呢?最简单的方法就是使用非可变类型的对象(见【第13条】)。因为无论什么时候,非可变类的状态都是不可改变的。 对于可变对象,常见的方法是在对其进行处理之前,先做参数有效...2009-06-15 11:23:44 · 143 阅读 · 0 评论 -
【第45条】在细节消息中包含失败-捕获信息
这一条是写给那些自己写Exception的程序员的。 为了在异常发生后捕捉失败原因,一个异常的字符串表示应该包括所有“对该异常有贡献”的参数和域的值。也就是说在异常所能“携带”的信息中,尽量多的加入对调试人员有用的信息。 一个例子是 IndexOutOfBoundsException ,在这个下标越界的异常中,提示出了,最小小标、最大下标和当前下标的值,这样...2009-06-15 10:54:54 · 138 阅读 · 0 评论 -
【第44条】每个方法抛出的异常都要有文档
虽然在【第40条】中说到了,Java的throws语法的一大好处是,即使没有文档也可以知道要调用的方法都会抛出哪些异常。但是,绝对不推荐你这么做。一定要写好文档。 通过@throws标签,逐个地声明每一个被检查的异常,并写清每一个异常被抛出的条件(这个是通过throws语句所了解不到的)。如果一个方法可能抛出多个异常,不要用它们共通的父类异常来表示。甚至,有人连会抛出哪些异...2009-06-09 17:12:47 · 182 阅读 · 0 评论 -
【第43条】抛出的异常要合适于相应的抽象
如果一个方法抛出的异常与它所执行的任务没有明显关联关系的话,会使人感到不知所措。为了避免这个问题,应该在高层的实现中俘获底层抛出的“低级”异常,并同时用另一“高级”异常继续向外抛。 例如,如我们在方法中,有一段循环,一个一个地取集合的一下元素。当catch到一个 NoSuchElementException 或 NullPointerException 时,说明已经到头儿了。...2009-06-09 16:52:32 · 289 阅读 · 0 评论 -
【第42条】尽量使用标准的异常
代码重用,是程序员们“千百年来”所追求的目标,同样Exception也是代码,也该尽量被重用。所以,应该尽量使用标准的异常,而不是轻易地使用自造的异常。 很多的类库都定义了自己的异常,我本人所参与设计的几个项目大多数也有自己的异常。但这些异常都是仅适用于项目自身的某些情形的,换个角度说,就是这些情形下没有太合适的标准异常来表示,加之自造异常还可以做某些处理,如信息的反馈,日...2009-06-09 16:37:28 · 153 阅读 · 0 评论 -
【第41条】避免不必要地使用被检查的异常
也就是说,在使用checkedException时,你必须确认这里的的确确是应该抛出一个异常,否则不要乱抛。如果一个方法会抛出一个或者多个被检查的异常,那么调用该方法的代码就必须要么在一个或几个try-catch块中处理这些异常,要么就要声明(throws)它们,以便向上抛出去。而无论哪种方法,都给程序员增添了不可忽略的负担。 回想一下上一条最后一段关于.Net为什么选择了更...2009-06-09 16:21:06 · 181 阅读 · 0 评论 -
【第40条】对于可恢复的条件使用被检查的异常,对于程序错误使用运行时异常...
Java一共有三种可抛出的东东(trhowable):被检查的异常(checkedException),运行时异常(runtimeException),错误(error)。我们最常见的是前两者,但是什么时候该使用哪种异常,可能是一件非常让人头疼的事情。为此,搜索“checkedException runtimeException”关键字,可以得到不少的讲解,比如我收藏的这一篇:http:/...原创 2009-06-09 12:09:08 · 202 阅读 · 0 评论 -
【第39条】只针对不正常的条件才使用异常
《第8章 异常》 异常是Java语言中非常重要、而又容易被轻视的、一个出于非常奇妙的地位的一个东东。这一章讲了关于有效使用异常的指导性原则。 【第39条】只针对不正常的条件才使用异常 异常只应该被用于不正常的情况,它们永远不应该被用于正常的控制流。书中举了一个特殊的例子,在这个例子中,循环的结束条件是当数组下标出界时引发的一个 ArrayIndexOutOf...2009-06-09 11:28:32 · 204 阅读 · 0 评论 -
【第38条】遵守普遍接受的命名惯例
Java平台(其实整个编程界)有着一套很好的命名惯例。所谓惯例,可以理解为“约定俗成”。类似我们常见的《命名规则》《编码规则》《SQL文规则》等,经过提炼,可以基本看出里面的“规律”。 “约定”对于编程来说,意义远大于在其他领域。在Rails中,甚至是“约定大于配置”的。 具体到Java的一系列命名惯例,首先是包名。和.Net中的namespace类似,Ja...2009-06-03 17:15:52 · 315 阅读 · 0 评论 -
【第25条】谨慎设计方法的原型
本条是一些小的技巧(或者说好习惯)的总结。 1)谨慎选择方法的名字 你选用的名字应该遵循标准命名习惯(见【第38条】),选择易懂的、并和他人保持风格一致的名字。比如用remove还是delete,通过看JDK文档的字母索引你就会发现前者比后者多得多。但是,我还是在一个方法中使用了delete。那是因为它确实是一个对数据表中数据的delete操作方法,而且在java.sql...2009-05-21 16:40:59 · 114 阅读 · 0 评论 -
【第24条】需要时使用保护性拷贝
Java受欢迎的一个重要原因是它是一门安全的语言。它对于缓冲区溢出、数组越界、非法指针以及其他内存破坏错误自动免疫。 但是,这并不是说你可以高枕无忧,正如前面【第5条】中所述的,某些情况下你还是要自行回收过期引用的。现在我们再来说一下你不得不做的“自我防卫”性工作。 【第5条】中的回收过期引用,即使你没有这么做,顶多是浪费一些内存资源。但是,如果本条所述的“...2009-05-19 16:04:50 · 130 阅读 · 0 评论 -
【第23条】检查参数的有效性
《第6章 方法》 方法,或称之为函数,是我们要最常打交道的。这一章讲述了“如何写好方法”,重点是可用性、健壮性和灵活性。这章中介绍的“技巧”都可以作为提高基本功素质的教材。 【第23条】检查参数的有效性 绝大多数方法和构造函数都对传入的参数有某些限制,如索引必须是非负数,对象引用不能是null,等等。如果一个无效的参数传入,应该首先对参数进行检查,如果...2009-05-19 15:03:22 · 298 阅读 · 0 评论 -
【第10条】谨慎地改写clone
原作者在这一条上用了8页的篇幅,翻译版也有7页,足以说明这一条的重要性。我个人对此条的标注是重量级的5颗星! 克隆——是一个很让人“感兴趣”而又“颇有争议”的话题,无论是在生物界还是在代码的世界中。 Java通过实现Cloneable接口来“说明”一个类支持clone方法。所谓clone就是返回一个当前对象的副本,注意这里所返回的是一个复制品,虽然它的内容应...2009-05-11 12:40:25 · 186 阅读 · 0 评论 -
【第9条】总是要改写toString
所有类都应该有一个toString方法,这也是Object的约定。很明显在实际使用中,同样也是,每个类的实例对象,都该有个方法将人们感兴趣的内容以String类型返回,在没有跟踪工具的年代,我们就是靠着Debug这些toString来调试程序的。 这一条其实没有什么太多可写的,只要记住一点即可“将你所关心的、感兴趣的部分toString了就可以了”。现今而言,由于有了Ecl...2009-05-11 10:32:24 · 200 阅读 · 0 评论 -
【第8条】改写equals时总是要改写hashCode
一个很常见的错误根源在于没有改写hashCode方法。在每一个改写了equals的方法的类中,你必须也要改写hashCode方法。如果不这么做的话,就会违反Object.hashCode的通用约定,从而导致该类无法与所有基于散列值(hash)的集合类结合在一起正常运行,这样的集合类包括HashMap、HashSet、Hashtable。 可能有人会问:什么是hash?它是干什么用...2009-05-10 22:13:14 · 175 阅读 · 0 评论 -
【第7条】在改写equals的时候请遵守通用约定
《第3章 对所有对象都通用的方法》 这是我认为最有用的一章,真的该好好问问自己,这些最最基础的东西,自己都掌握吗? Object是个即普通又特殊的类。说它普通是因为所有的类都是由它派生来的,说它特殊是因为它是所有其他类的父类必须先了解它才能写好你自己的类。 Object所有的非final方法,都是为改写(override)而设计的,改写方法都有明确的约定,这一章就是讲述该如何...2009-05-10 21:28:05 · 116 阅读 · 0 评论 -
【第6条】避免使用终结函数
终结函数(finalizer)通常是不可预测的,常常也是很危险的,一般情况下不是必要的。使用终结函数会导致不稳定的行为、更差的性能,以及带来移植性问题。不要把终结函数当做C++中的析构函数(destructors)的对应物。 我自己总结了一下这一条的综合性结论是这样的:1)在涉及使用资源,使用完毕后要释放资源的情形下,首先要用一个显示的方法(应该是私有的)来释放这些资源...2009-05-05 10:58:00 · 130 阅读 · 0 评论 -
【第5条】消除过期的对象引用
我们喜爱Java的其中一个原因就是它的垃圾回收机制。绝大部分情况下,JVM都能过自动回收垃圾。 但是,在有些情形下,你还是要自己回收垃圾的,这些情形多是JVM无从通过“物理”性质来识别垃圾,而需要程序员通过“逻辑”性来判断哪些是垃圾并回收之。 所以,在支持垃圾回收的语言中,内存泄漏更应该被称之为“无意识的对象保持”。 例子:我们有两个String数组: a[10...2009-05-05 10:29:50 · 108 阅读 · 0 评论 -
【第4条】避免创建不必要的对象
此条在中文版第二版中被译为了“避免创建不必要的对象”,用此更加严谨了。 此条认为重复使用同一对象,比每次需要时都创建一个功能上相等价的新对象更好。如果对象是非可变的(见【第13条】),那么他总是可以被重用的。 一例子是:String s1 = "Hello World !";........ // 其他一些列代码String s2= "Hello World !";...2009-05-05 10:10:10 · 101 阅读 · 0 评论 -
【第3条】通过私有构造函数强化不可实例化的能力
有时候你可能编写出只包含静态方法和静态域的类。这样的类有一些很不好的名声,因为有些人在面向对象的语言中滥用这样的类来编写过程化的程序。 对原文这句话的理解,我有着深刻的印象,有很多从VB6工程转过来做Java或C#(包括VB.Net)的程序员,在抱怨:还是VB6好用,各种方法简单明了,像什么 left() trim() split() cstr() replace...2009-05-04 12:42:26 · 145 阅读 · 0 评论 -
【第2条】用私有构造函数强化singleton属性
singleton即单例模式。【第1条】中我提到的Session性质的全局唯一实例既是单例模式。它只能被实例化一次,通常代表本质上具有唯一性质的东西。 除了Session的例子外,我这里还有一个很微妙的例子: new MessageBox("Hello World ! ").show(); MessageBox.show(new MessageBox("Hell...2009-05-04 11:07:13 · 111 阅读 · 0 评论 -
【第1条】考虑用静态工厂方法代替构造函数
《第2章》创建和销毁对象(第1~6条) 【第1条】考虑用静态工厂方法代替构造函数 所谓静态工厂方法,实际上只是一个简单的静态方法,它返回的是类的一个实例。使用静态工厂方法的好处:1)它与构造函数不同,它有名字,你可以把名字起的更易于阅读。 如果你想让2个构造函数拥有相同个数和类型的参数,这将是无法实现的;即使是2个不同类型的参数顺序倒置的,使用者也非常容易搞...2009-05-04 10:24:22 · 263 阅读 · 0 评论 -
【第11条】考虑实现Comparable接口
与本章(前面3条)所讨论的方法不同,compareTo方法在Object中并没有被声明,它是java.lang.Comparable接口中唯一的方法。实现这一接口,也可以说类具有了“内在排序能力”。 compareTo方法除了允许比较相等外,还可以比较大小。通常如果 x < y ,则 x.compareTo(y) 返回一个负整数(通常是 -1);如果 x.equ...2009-05-11 15:40:09 · 138 阅读 · 0 评论 -
【第12条】使类和成员的可访问能力最小化
《第4章 类和接口》 类和接口是Java语言的核心,本章包含的一些指导原则,可以帮助你更好地设计出更加有用、健壮、灵活的类和接口。 【第12条】使类和成员的可访问能力最小化 要想区别一个设计良好的模块与一个设计不好的模块,最重要的因素是,这个模块对于外部的其它模块而言,是否隐藏了内部的数据和其他的实现细节。换句话说,就是模块的设计者是否对其进行了良好的封装。...2009-05-12 14:18:06 · 133 阅读 · 0 评论 -
【第22条】用类和接口来代替函数指针
C语言中的函数指针又叫回调(callback)。是用参数传入一个函数指针,调用函数就可以根据不同的传入参数,实际上调用不同的函数了。 这种回调在ActionScript3语言中就是Function类型,Flex的事件监听器就是一个典型的使用场景。将一个Function类型所表示的函数作为参数传给事件监听器,当此事件发生时,就自动调用这个函数。 在设计模式中的...2009-05-19 14:36:16 · 191 阅读 · 0 评论 -
【第21条】用类来代替enum结构
要先说明一下:本书写作于2001年,正值作者参与建设JDK1.4的时期。后来到了JDK1.5,Java又将抛弃了多年的enum枚举重拾了起来。所以本条是在没有enum的时候写的。 JDK1.4及以前版本省略了enum。其实enum也是一种struct,我们当然是用class来代替之,但为什么又要单独作为一条来讲呢?是因为用类来替代枚举的时候,比较容易(或者说事实中绝大多数人都已经)...2009-05-18 17:16:54 · 221 阅读 · 0 评论