从书堆里翻出了这本书,虽然不干JAVA好多年,但原理都是差不多的,顺便看下了。觉得有意思的就写了点,没意思的就写个标题。
顺便也贴个Effective C#中文版:http://hi.baidu.com/chenying99/blog/item/101ab4259ff7386835a80fd7.html
第2章 创建和销毁对象
第1条:考虑用静态工厂方法代替构造函数
从文章内容来看是用静态工厂方法表达更为清楚。
第2条:使用私有构造函数强化singleton属性
2 private static final Foo Instance = new Foo();
3
4 private Foo(){}
5
6 public static Foo getInstance(){
7 return Instance
8 }
9 }
第3条:通过私有构造函数强化不可实例化的能力
用抽象类来强制该类不可被实例化,行不通的,继承该类的子类都可以被实例化。容易让人产生错觉,认为这个抽象类是为继承而设计的。
将类显示的私有构造函数,则它就可以被实例化了。
第4条:避免创建重复的对象
string s = new string(“smile”); // wrong
string s = “smile”;
第5条:消除过期的对象引用
第6条:避免强制垃圾回收
第3章 对于所有对象都通用的方法
第7条:在改写equals的时候请遵守通用约定
第8条:改写equals时总是要改写hashCode
第9条:总是要改写toString()
第10条:谨慎地改写clone
第11条:考虑实现Comparable接口
可以参考 http://www.cnblogs.com/anytao/archive/2009/04/12/anytao_devstory_03_customcomparison.html
第4章 类和接口
第12条:使类和成员的可访问能力最小化
第13条:支持非可变性
不提供任何修改对象的方法和保证没有可被子类改写的方法。只提供读方法,这个对象本质上时线程安全的。
第14条:复合优先于继承
继承是实现代码复用的有力手段。但是继承也打破了类的封装性【超类的实现可能会被修改】。
可以参考一些设计模式。比较典型的就是装饰模式:http://www.cnblogs.com/Terrylee/archive/2006/07/17/334911.html
第15条:要么专门为继承而设计,并给出文档说明,要么禁止继承
对于一个不是为了继承而设计并且没有说明文档的父类进行子类化是很危险的。
为继承而设计的类,要求对这个类有一些实质性的限制。如果那些并非为了进行子类化设计和编写文档的类,禁止子类化。
第16条:接口优于抽象类
我觉得应该说清楚它们的共性和特性。
共性:a.都不能被实例化。 b.通过继承实现其接口或抽象方法。
特性:接口:a.支持多继承。b.只能定义抽象规则。c.支持回调
抽象类:a.只能单继承。b.技能定义抽象规则也可以实现方法。c.回调有局限 d.继承类必须实现父类抽象方法。
第17条:接口只是被用于定义类型
第18条:优先考虑静态成员类
第5章 C语言结构的替代
第19条:用类代替结构
第20条:用类层次来代替联合
第21条:用类来代替enum结构
2 public static readonly int Doing =1;
3 public static readonly int Finished =2;
4 public static readonly int Cancel =3;
5 }
6
7 enum orderState
8 {
9 Doing,Finished,Cancel
10 }
11
第22条:用类和接口来代替函数指针
第6章 方法
第23条:检查参数的有效性
第24条:需要时使用保护性拷贝
第25条:谨慎设计方法的原型
a.谨慎选择方法的名字。我认为应该从规约限定。按照特定行业对行为和属性描述的单词。
b.不要过于追求提供便利的方法。
c.避免过长的参数列表。
d.对于参数类型,优先使用接口而不是类。
我很赞同。参考.net framework中就有很多典型的例子。比如Tostring(IFormateable) 和Array.Sort(ICompareable)
e.谨慎地使用函数对象。
第26条:谨慎地使用重载
第27条:返回零长度的数组而不是null
2 {
3 return null;
4 }
5
6 public List getList2()
7 {
8 return new List(0);
9 }
10
11 public void main(){
12 // call 1
13 List list = getList1();
14 if(list ==null)
15 throw new NullPointerException();
16 if(list.contains("china"))
17 {
18 //do something
19 }
20 // call 2
21 List list = getList2();
22 if(list.contains("china"))
23 {
24 //do something
25 }
26 }
第28条:为所有导出的API元素编写文档注释
第7章 通用程序设计
第29条:将局部变量的作用域最小化
第30条:了解和使用库
第31条:如果要求精确的答案,请避免使用float和double
float和double类型对于货币计算非常不适合。【还好.NET提供decimal类型】
第32条:如果其他类型更适合,则尽量避免使用字符串
字符串不适合代替其他值类型。容易发生box&unbox。至于对象的话那更没有意义了。
第33条:了解字符串连接的性能
每本书都一样。建议使用StringBuilder
第34条:通过接口引用对象
面向接口编程就是为了解耦。
可以参考以下2篇文章:
http://www.cnblogs.com/yuanhuaming/archive/2009/09/24/1573231.html
http://www.cnblogs.com/wayfarer/archive/2009/11/10/1600467.html
第35条:接口优先于反射机制
反射虽然很好用也很实用。但是由于性能的损失让人不得不想尽其它方法解决问题。.net4.0的动态类就是一个不错的选择。
使用反射请考虑利弊关系。
第36条:谨慎地使用本地方法 莫名其妙
第37条:谨慎的进行优化
优化的第一条原则就是不要因为性能而牺牲合理的结构。
第38条:遵守普遍接受的命名惯例
第8章 异常
第39条:只针对不正常的条件才使用异常
第40条:对于可恢复的条件使用被检查的异常,对于程序错误使用运行时异常
第41条:避免不必要的是使用被检查的异常
第42条:尽量使用标准的异常
第43条:抛出的异常要适合于相应的抽象
高层的实现应该捕获地层的异常,同时抛出一个可以按照高层抽象进行解释的异常。
我的做法就是高层捕获低层异常。直到UI层进行捕获处理。
第44条:每个方法抛出的异常都要有文档
第45条:在细节消息中包含失败-捕获信息
第46条:努力使失败保持原子性
第47条:不要忽略异常
不要出现空的catch块会使异常达不到应有的目的。
第9章 线程
第48条:对共享可变数据的同步访问
第49条:避免过多的同步
第50条:永远不要在循环的外面调用wait
第51条:不要依赖于线程调度器
第52条:线程安全性的文档化
第53条:避免使用线程组
第10章 序列化
第54条:谨慎地实现Serializable
第55条:考虑使用自定义的序列化形式
第56条:保护性地编写readObject方法
第57条:必要时提供一个readResolve方法