Effective java 2

一、考虑用静态工厂方法代替构造器。
优点:
1、名称。
2、不必每次调用都新创建对象。
3、可以返回原返回类型的任何子类型的对象。
4、创建参数化类型实例时,使代码变得更简洁。
缺点:
1、类如果不含公有的或受保护的构造器,就不能被子类化。
2、与其他的静态方法实际上没有任何区别。


二、遇到多个构造器参数时要考虑用构建器。
builder模式,即不直接生成想要的对象,客户端在builder对象上调用类似于setter的方法,来设置每个相关的可选参数;最后客户端调用无参的build方法来生成不可变的对象。
避免多个构造参数的问题,但是需要先创建构建器的开销。


三、用私有构造器或者枚举类型强化Singleton属性 。


四、通过私有构造器强化不可实例化的能力。


五、避免创建不必要的对象。


六、消除过期的对象引用。(常见集合;引起内存泄漏)


七、避免使用终结方法。

终结方法通常是不可预测的,也是很危险的,一般情况下是不必要的。
Java语言规范不仅不保证终结方法会被及时地执行,而且根本就不保证他们会被执行。
使用终结方法有一个非常严重的性能损失。


八、覆盖equals时请遵守通用约定
1、类的每个实例本质上都是唯一的。
2、不关心类是否提供了“逻辑相等”的测试功能。
3、超类已经覆盖了equals,从超类继承过来的行为对于子类也是合适的。
4、类是私有的或是包级私有的,可以确定他的equals方法永远不会被调用。
5、equals等价关系:自反性、对称性、传递性、一致性、对于任何非null的引用值x,x.equals(null)必须返回false。


九、覆盖equals时总要覆盖hashCode。


十、始终要覆盖toString。


十一、谨慎地覆盖clone。


十二、考虑实现Comparable接口。


十三、使类和成员的可访问性最小化。(即信息隐藏或封装)


十四、在公有类中使用访问方法而非公有域。


十五、使可变性最小化。

使类成为不可变,遵循以下规则:
1、不要提供任何会修改对象状态的方法。
2、保证类不会被扩展。
3、使所有的域都是final的。
4、使所有的域都成为私有的。
5、确保对于任何可变组件的互斥访问。


十六、复合优先于继承。
复合:新类中的每个实例方法都可以调用被包含的现有类实例中对应的方法,并返回它的结果,新类中的方法称为转发方法。


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


十八、接口优于抽象类。

1、现有的类可以很容易被更新,以实现新的接口。
2、接口是定义mixin(混合类型)的理想选择。
3、接口允许我们构造非层次结构的类型框架。


十九、接口只用于定义类型。
常量接口模式是对接口的不良使用。


二十、类层次优于标签类。


二十一、用函数对象表示策略。

使用继承接口实现策略方法,当策略只被使用一次时,通常使用匿名类声明和实例化这个具体策略类。


二十二、优先考虑静态成员类。
如果内部类需要外围实例的引用,需要定义为非静态;否则定义为静态;如果只需要在一个地方创建实例并且已经有了一个预置的类型可以说明这个类的特征,定义为匿名类;否则定义为局部类。


二十三、请不要在新代码中使用原生态类型。(如集合set<string>不要直接使用set)


二十四、消除非受检警告。


二十五、列表优先于数组。


二十六、优先考虑泛型。


二十七、优先考虑泛型方法。


二十八、利用有限制通配符来提升API的灵活性。

producer-extends,consumer-super(PECS)


二十九、优先考虑类型安全的异构容器。(如Class<T>)


三十、用enum代替int常量。


三十一、用实例域代替序数。


三十二、用EnumSet代替位域。


三十三、用EnumMap代替序数索引。


三十四、用接口模拟可伸缩的枚举。


三十五、注解优先于命名模式。


三十六、坚持使用Override注解。


三十七、用标记接口定义类型。


三十八、检查参数的有效性。


三十九、必要时进行保护性拷贝。


四十、谨慎设计方法签名。

1、谨慎地选择方法的名称。
2、不要过于追求提供便利的方法。
3、避免过长的参数列表。


四十一、慎用重载。


四十二、慎用可变参数。


四十三、返回零长度的数组或者集合,而不是NULL


四十四、为所有导出的API元素编写文档注释。


四十五、将局部变量的作用域最小化。


四十六、for-each循环优先于传统的for循环。

以下无法使用for-each:
过滤、转换、平行迭代。


四十七、了解和使用类库,避免重复造轮子。


四十八、如果需要精确的答案,请避免使用float和double。

如果性能优先且不介意记录十进制小数点,数值不大可以使用int或者long。
如果数值范围没有超过9位十进制,使用int;如果不超过18位十进制数字,使用long。
如果数值可能超过18位数字,就必须使用BigDecimal


四十九、基本类型优先于装箱基本类型。(使用装箱类型特别注意==操作符)


五十、如果其他类型更合适,则尽量避免使用字符串。

1、字符串不适合代替其他的值类型。
2、字符串不适合代替枚举类型。
3、字符串不适合电梯聚集类型。
4、字符串不适合代替能力表。


五十一、当心字符串连接的性能。


五十二、通过接口引用对象。


五十三、接口优先于反射机制。

反射机制缺点:
1、丧失了编译时类型检查的好处。
2、执行反射访问所需要的代码非常笨拙和冗长。
3、性能损失。


五十四、谨慎地使用本地方法。


五十五、谨慎地进行优化。

1、不要因为性能而牺牲合理的结构。
2、努力避免那些限制性能的设计决策。
3、要考虑API设计决策的性能后果。
4、API设计对于性能的影响是非常实际的。
5、性能剖析工具有助于你决定应该把优化的重心放在哪里。


五十六、遵守普遍接受的命名惯例。(驼峰命名法)


五十七、只针对异常情况才使用异常。


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


五十九、避免不必要地使用受检的异常。


六十、优先使用标准的异常。


六十一、抛出与抽象相对应的异常。


六十二、每个方法抛出的异常都要有文档。


六十三、在细节消息中包含能捕获失败的信息。


六十四、努力使失败保持原子性。


六十五、不要忽略异常。


六十六、同步访问共享的可变数据。


六十七、避免过度同步。


六十八、executor和task优先于线程。


六十九、并发工具优先于wait和notify。

常用CountDownLatch和Semaphore不常用CyclicBarrier和Exchanger


七十、线程安全性的文档化。


七十一、慎用延迟初始化。


七十二、不要依赖于线程调度器。


七十三、避免使用线程组。


七十四、谨慎地实现Serializable接口。

1、实现Serializable接口而付出的最大代价是,一旦一个类被发布,就大大降低了“改变这个类的实现”的灵活性。
2、增加了出现Bug和安全漏洞的可能性。
3、随着类发行新的版本,相关的测试负担也增加了。


七十五、考虑使用自定义的序列化形式。


七十六、保护性地编写readObejct方法。

1、对于对象引用域必须保持为私有的类,要保护性地拷贝这些域中的每个对象。不可变类的可变组件就属于这一类别。
2、对于任何约束条件,如果检查失败,则抛出一个InvalidObjectException异常。这些检查动作应该跟在所有的保护性拷贝之后。
3、如果整个对象图在被反序列化之后必须进行验证,就应该使用ObjectInputValidation接口。
4、无论是直接方式还是间接方式,都不要调用勒种任何可被覆盖的方法。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值