一、引言

  1.几条基本规则:(清晰性和简洁性最为重要)

      模块的用户永远也不应该被模块的行为所迷惑(那样就不清晰了),模块要尽可能小,但又不能太小

      代码应该被重用,而不是被拷贝

      模块之间的依赖性应该尽可能的降到最小

      错误应该尽早的被检测出来,最好是在编译时刻

      PS.你不该盲目的遵从这些规则,但是,你应该只在偶尔的情况下,有了充分理由之后采取打破这些规则

      学习编程艺术首先要学会基本的规则,然后才能知道什么时候可以打破这些规则

二、创建和销毁对象

  第一条:考虑用静态工厂方法代替构造器。它有以下优势:

    1)它有名称

    2)不必再每次调用它的时候都创建一个新对象

    3)它可以返回原类型的任何子类型的对象

    4)在创建参数化类型实例的时候,它使代码变得更加简洁

    缺点:

    1)类如果不含共有的或者受保护的构造器,就不能被子类化(它鼓励程序复用而不是继承)

    2)它与其他的静态方法实际上没有任何区别(API文档中无法明确表示出来,可以用惯用命名来弥补)

  第二条:遇到多个构造器参数时要考虑用构建器。一般常用方法:

    1)重叠构造器(telescoping constructor)

    2) JavaBean模式

    3)build构建器

      PS.语法糖:NutritionFacts cocaCola = new NutritionFacts.Builder(240,8).calories(100).sodium(35).carbonydrate(27).build();

  第三条:用私有构造器或者枚举类型强化Singleton属性

  第四条:通过私有构造器强化不可实例化的能力

  第五条:避免创建不必要的对象:

    1)不要用String s = new String("xxxx");而应该用String s = "xxxxx";前者复用会创建大量实例,后者只会创建一个

    2)不要使用Boolean(String);而应该用Boolwan.valueOf(String);对于同时提供了静态工厂方法和构造器的不可变类,通常用静态方法,避免创建不必要的对象

    3)用long sum = 0L;而不要用Long sum = 0L;要优先使用基本类型而不是装箱基本类型,要当心无意识的自动装箱

    4)现代的JVM实现具有高度优化的垃圾回收器,其性能很容易就会超过轻量级对象池的性能,因此除非重量级对象(数据库连接),少用线程池。

  第六条:消除过期的对象引用(主要是为了防范内存泄露):

    1)栈里被弹出的元素,记得要清空引用

    2)缓存用WeakHashMap来实现

    3)注意监听器和其他回调,保存对象的弱引用,例如,只将他们保存成WeakHashMap

  第七条:避免使用终结方法(finalizer)

    原因:它不能及时执行,甚至根本就不保证它们会被执行

    用处:充当安全网,或者是为了终止非关系的本地资源

    用法:记得调用super.finalizer;要记得记录终结方法的非法方法;考虑使用终结方法守卫者

三、对于所有对象都通用的方法

  第八条:覆盖equals时请遵守通用约定

    1)自反性

    2)对称性

    3)传递性

    4)一致性

    ps.使用诀窍在P36

  第九条:覆盖equals时总要覆盖hashCode

    约定内容:

      1) 如果两个对象相同,那么它们的hashCode值一定要相同。重写equals方法,一定要重写hashCode方法。

      2) 如果两个对象的hashCode相同,它们并不一定相同,这里的对象相同指的是用eqauls方法比较。

    PS.Hash算法原理:当Set接收一个元素时根据该对象的内存地址算出hashCode,看它属于哪一个区间,在这个区间里调用equeals方法。

  第十条:始终要覆盖toString方法

  第十一条:谨慎的覆盖clone

    由于它有许多缺点,另一个实现对象拷贝的好办法是提供一个拷贝构造器或者拷贝工厂

  第十二条:考虑实现Comparable接口

    有些类具有内在的排序功能,但是与equals不一致。有些集合使用comparable而不是equals做同性测试。

四、类和接口

  第十三条:使类的成员的可访问性最小化

    封装:又被称为信息隐藏,是模块化的前提和保证

    模块化的好处:

      1)各个模块可以独立开发、测试、优化、使用、理解和修改

      2)加快系统开发的速度,因为这些模块可以并行开发

      3)减轻了维护的负担,程序员可以更快的理解模块,而且在调试的时候可以不影响其他维护的负担

      4)虽然模块本身不会带来更好的性能,但是它可以帮助调节性能,通过分析知道哪些模块影响了性能

      5)提高软件的可重用性,模块可以在其它系统中使用

      6)模块可以降低系统风险,整个系统不可用,但是模块却有可能是可用的

  第十四条:在公有类中使用访问方法而非公有域

    变量应该用private定义而不是public的,只能用get/set方法取

    但是如果这个类是包级私有(default)的,或者是内部类的话,则没有关系

  第十五条:使可变性最小化

    使类变为不可变的5条规则:

      1)不要提供任何会修改对象状态的方法(也称为mutator)

      2)保证类不会被扩展(使类成为final的,或者限制访问构造器)

      3)使所有域都是final的

      4)使所有域都是私有的

      5)确保对于任何可变组件的互斥访问(如果能set则不能get对象的引用)

    不可变的类(如复数类),被称作函数(functional)式的做法,相对的是过程(procedural)式的做法和命令(imperative)式的做法

    不可变的类往往有一个可变配套类,来弥补它性能上的缺点(String->StringBuilder)

    坚决不要为每个get方法编写一个相应的set方法,除非有很好的理由。不可变类有很多优点,唯一缺点是潜在的性能问题

  第十六条:复合优先于继承:继承的功能非常强大,但是也存在诸多问题,因为它违背了封装原则。只有当子类和超类之间确实存在子类型关系时,使用继承才是恰当的。否则,可以使用复合来代替继承。    

   第十七条:要么为继承而设计,并提供文档说明,要么就禁止继承

  第十八条:接口优于抽象类:除非演变的容易性比灵活性和功能性更为重要的时候

  第十九条:接口只用于定义类型:常量接口模式是对接口的不良使用,应该使用工具类(utility class)

  第二十条:类层次优于标签类:合理设计类,不要在一个类里塞太多东西,而应该使用抽象类之类的方法分层

  第二十一条:用函数对象表示策略:函数指针的主要用途就是实现策略(Strategy)模式

  第二十二条:优先考虑静态成员变量:四种不同的嵌套类及用法

五、泛型

  第二十三条:请不要在新代码中使用原生态类型(关于List<?>,一般用于只读模式,因为不知道里面元素的类型,所以不能执行add方法,除非是null。常在方法中出现,限制方法乱add元素,出于安全性考虑。)

   第二十四条:消除非受检警告:使用@SuppressWarnings("unchecked"),并添加注释,尽量加在行上而不要加在方法上。

   第二十五条:列表优先于数组:优先使用泛型而不是数组来存数据,因为泛型是编译时检查类型,而数组是运行时检查,前者更安全。数组和泛型不要混合用。

  第二十六条:优先考虑泛型

  第二十七条:优先考虑泛型方法

  第二十八条:利用有限制通配符来提升API的灵活性:PECS原则(P119)

  第二十九条:优先考虑类型安全的异构容器

六、枚举和注解

  第三十条:用enum代替int常量

  第三十一条:用实例域代替序数

  第三十二条:用EnumSet代替位域    

  第三十三条:用EnumMap代替序数索引

  第三十四条:用接口模拟可伸缩的枚举

  第三十五条:注释优于命名模式

  第三十六条:坚持使用Override注解

  第三十七条:用标记接口定义类型(标记注解和标记接口各有用处)

七、方法

  第三十八条:检查参数的有效性

  第三十九条:必要时进行保护性拷贝

  第四十条:谨慎设计方法签名

  第四十一条:慎用重载:重载的话,最好保证参数数目不一致,或者所有重载方法的行为一致。否则程序很容易误入重载方法。

  第四十二条:慎用可变参数:3个以下的参数用重载

  第四十三条:返回零长度数组或是集合,而不是null

  第四十四条:为所有导出的API元素编写文档注释

八、通用程序设计

  第四十五条:将局部变量的作用于最小化:

    1.不要过早的声明变量,而应该在他第一次使用的地方声明

    2.声明时应该初始化变量,除非是特殊情况(try块内)

    3.for循环优先于while循环,因为有循环变量可以使用

    4.使方法小而集中,也可以将局部变量的作用域最小化

  第四十六条:for-each循环优于传统的for循环

  第四十七条:了解和使用类库:程序员应该把时间花在应用程序上,而不是底层的细节上。不要重复造轮子

  第四十八条:如果需要精度的答案,请避免使用float和double:应该使用BigDecimal处理小数,或者int和long处理整数

  第四十九条:基本类型优先于装箱基本类型:当装箱基本类型和基本类型比较时,装箱基本类型会自动拆箱。如果null对象被自动拆箱,会报NullPointerException异常

  第五十条:如果其他类型更合适,则尽量避免使用字符串:字符串经常被错误的用来代替基本类型、枚举类型和聚合类型等

  第五十一条:当心字符串连接的性能

  第五十二条:通过接口引用对象:优先使用接口,这样会更灵活更聪明

  第五十三条:接口优于反射机制:应该仅仅使用反射机制来实例化对象,而访问对象时则使用编译时已知的某个接口或者超类

  第五十四条:谨慎的使用本地方法

  第五十五条:谨慎的进行优化:不要费力去编写快速的程序——应该努力编写好的程序,速度自然会随之而来

  第五十六条:遵守普遍接受的命名惯例

九、异常

  第五十七条:只针对异常的情况才使用异常:逻辑控制中,应该使用“状态测试方法”或“可识别的返回值”方法,而不是把异常用于控制流

  第五十八条:对可恢复的情况使用受检异常,对编程错误使用运行时异常

  第五十九条:避免不必要的使用受检的异常

  第六十条:优先使用标准的异常

  第六十一条:抛出与抽象对应的异常

  第六十二条:每个方法抛出的异常都要有文档

  第六十三条:在细节消息中包含能捕获失败的信息

  第六十四条:努力使失败保持原子性

  第六十五条:不要忽略异常

十、并发

  第六十六条:同步访问共享的可变数据

  第六十七条:避免过度同步

  第六十八条:excutor和task优先于线程

  第六十九条:并发工具优先于wait和notify

  第七十条:线程安全性的文档化

  第七十一条:慎用延迟初始化

  第七十二条:不要依赖线程调度器:确保可运行线程的平均数量不明显的多于处理器的数量

  第七十三条:避免使用线程组(thread group),已基本废弃,应该使用线程池executor

十一、序列化

  第七十四条:谨慎的实现Serializable接口

  第七十五条:考虑使用自定义的序列化形式

  第七十六条:保护性的编写readObject方法

  第七十七条:对于实例控制,枚举类型优先于readResolve

  第七十八条:考虑用序列化代理代替序列化实例

《Effective Java》读书笔记的更多相关文章

  1. csapp读书笔记-并发编程

    这是基础,理解不能有偏差 如果线程/进程的逻辑控制流在时间上重叠,那么就是并发的.我们可以将并发看成是一种os内核用来运行多个应用程序的实例,但是并发不仅在内核,在应用程序中的角色也很重要. 在应用级 ...

  2. CSAPP 读书笔记 - 2.31练习题

    根据等式(2-14) 假如w = 4 数值范围在-8 ~ 7之间 2^w = 16 x = 5, y = 4的情况下面 x + y = 9 >=2 ^(w-1)  属于第一种情况 sum = x ...

  3. CSAPP读书笔记--第八章 异常控制流

    第八章 异常控制流 2017-11-14 概述 控制转移序列叫做控制流.目前为止,我们学过两种改变控制流的方式: 1)跳转和分支: 2)调用和返回. 但是上面的方法只能控制程序本身,发生以下系统状态的 ...

  4. CSAPP 并发编程读书笔记

    CSAPP 并发编程笔记 并发和并行 并发:Concurrency,只要时间上重叠就算并发,可以是单处理器交替处理 并行:Parallel,属于并发的一种特殊情况(真子集),多核/多 CPU 同时处理 ...

  5. 读书笔记汇总 - SQL必知必会(第4版)

    本系列记录并分享学习SQL的过程,主要内容为SQL的基础概念及练习过程. 书目信息 中文名:<SQL必知必会(第4版)> 英文名:<Sams Teach Yourself SQL i ...

  6. 读书笔记--SQL必知必会18--视图

    读书笔记--SQL必知必会18--视图 18.1 视图 视图是虚拟的表,只包含使用时动态检索数据的查询. 也就是说作为视图,它不包含任何列和数据,包含的是一个查询. 18.1.1 为什么使用视图 重用 ...

  7. 《C#本质论》读书笔记(18)多线程处理

    .NET Framework 4.0 看(本质论第3版) .NET Framework 4.5 看(本质论第4版) .NET 4.0为多线程引入了两组新API:TPL(Task Parallel Li ...

  8. C#温故知新:《C#图解教程》读书笔记系列

    一.此书到底何方神圣? 本书是广受赞誉C#图解教程的最新版本.作者在本书中创造了一种全新的可视化叙述方式,以图文并茂的形式.朴实简洁的文字,并辅之以大量表格和代码示例,全面.直观地阐述了C#语言的各种 ...

  9. C#刨根究底:《你必须知道的.NET》读书笔记系列

    一.此书到底何方神圣? <你必须知道的.NET>来自于微软MVP—王涛(网名:AnyTao,博客园大牛之一,其博客地址为:http://anytao.cnblogs.com/)的最新技术心 ...

  10. Web高级征程:《大型网站技术架构》读书笔记系列

    一.此书到底何方神圣? <大型网站技术架构:核心原理与案例分析>通过梳理大型网站技术发展历程,剖析大型网站技术架构模式,深入讲述大型互联网架构设计的核心原理,并通过一组典型网站技术架构设计 ...

随机推荐

  1. sphinx全文检索之PHP使用(转)

    基础 数据结构: CREATE TABLE email ( emailid mediumint(8) unsigned NOT NULL auto_increment COMMENT '邮件id', ...

  2. Vs 2008 解决方案的目录结构设置和管理(转)

    http://blog.csdn.net/lcj_cjfykx/article/details/8632459 MS的这个IDE,实在庞杂得恐怖.从大学开始,我就一直用VC的各个版本写程序至今,细细想 ...

  3. php转义和去掉html、php标签函数

    /** * 转义html字符 * * @param string|array $var */function fhtmlspecialchars($var) { if (is_array ( $var ...

  4. 你不知道的 Javascript

    作用域 词法作用域:编译阶段确定(欺骗词法作用域 eval with) function foo(str){ "use strict" eval(str) console.log( ...

  5. UNIX V6内核源码剖析——进程

    进程的概念 1. 什么是进程 2. 进程的并行执行 3. 进程的运行状态 4. 用户模式和内核模式 cpu具有2种模式——内核模式和用户模式,通过PSW来切换. 切换时, 映射到虚拟地址的物理内存区域 ...

  6. Java栈实现

    栈数组实现一:优点:入栈和出栈速度快,缺点:长度有限(有时候这也不能算是个缺点) public class Stack { private int top = -1; private Object[] ...

  7. webbroswer 后台注入脚本 的方法

    HtmlElement script = webBrowser.Document.CreateElement("script"); script.SetAttribute(&quo ...

  8. jquery_ajax

    一.调用 <script type="text/javascript" src="jquery-1.11.2.min.js"></script ...

  9. Python(2.7.6) 标准日志模块 - Logging Handler

    Python 标准日志模块使用 Handler 控制日志消息写到不同的目的地,如文件.流.邮件.socket 等.除了StreamHandler. FileHandler 和 NullHandler ...

  10. Java语言编写计算器(简单的计算器)

    Java编写的一个简单计算器,本人还比较菜,只能这样了,有点代码冗余,不能连续计算. import javax.swing.*; import java.awt.*; import java.awt. ...