Effective Java
-----------Effective Java™ Second Edition
1.考虑使用静态工厂方法而不是构造函数(Consider static factory methods instead of constructors
)
例如:Integer类中的:
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
其它原生类型对应的封装类型都有相应的静态工厂方法,而且每个类都重载了很多静态工厂方法。
一个类采用static factory methods ,而不是构造函数,有以下好处:有一个比较有意义的方法名字;调用方法不必每次都创建一个新对象(缓存);它可以返回类型的子类型;简化创建参数化类型对象实例,让编译器推倒类型;比如:
guava类Maps:
public static <K, V> HashMap<K, V> newHashMap() {
return new HashMap<K, V>();
}
比较常见的静态工厂函数名:
- valueOf—Returns an instance that has, loosely speaking, the same value as its parameters. Such static factories are effectively type-conversion methods.
• of—A concise alternative to valueOf, popularized by EnumSet(Item 32).
• getInstance—Returns an instance that is described by the parameters but cannot be said to have the same value. In the case of a singleton,get Instance takes no parameters and returns the sole instance.
• newInstance—Like getInstance, except that new Instance guarantees that each instance returned is distinct from all others.
• getType—Like getInstance, but used when the factory method is in a different class.Type indicates the type of object returned by the factory method.
• newType—Like new Instance, but used when the factory method is in a different class.Type indicates the type of object returned by the factory method.
2.构造函数或者静态工厂函数的参数过多时,可以使用构造器模式(builder pattern)(Consider a builder when faced with many constructor parameters)
3.用私有构造函数或者枚举类型强化单例属性(Enforce the singleton property with a private constructor or an enum type)
4.利用私有构造函数(也可以在私有构造函数内抛出异常)表达不可实例化的类(Enforce noninstantiability with a private constructor)
5.避免创建不必要的对象(对象缓存可以改善)(Avoid creating unnecessary objects)
6.清除过期对象的引用(一般情况下,良好的垃圾回收帮我们做了,但过期的对象必须让垃圾回收器知道的前提下)(Eliminate obsolete object references )
7.避免使用终结方法(Avoid finalizers )
终结方法相关的类与方法有:
重写Object类的方法:
protected void finalize() throws Throwable { }
调用System类的方法(及Runtime类与此实现相关的方法):
public static void gc() {
Runtime.getRuntime().gc();
}
public static void runFinalization() {
Runtime.getRuntime().runFinalization();
}
@Deprecated
public static void runFinalizersOnExit(boolean value) {
Runtime.runFinalizersOnExit(value);
}
8.覆盖equals 方法时要遵守通用约定(Obey the general contract when overridingequals )
9.覆盖equals 方法时总要覆盖hashCode 方法(Always overridehashCodewhen you overrideequals )
10.始终要覆盖toString 方法 (Always override toString )
11.谨慎的覆盖clone方法(Override clonejudiciously )
12.考虑实现Comparable接口(Consider implementing Comparable)
13.类及其成员的可访问性最小化(Minimize the accessibility of classes and members )
14.在公有类中,要使访问方法访问属性,而非直接使用公共属性(In public classes, use accessor methods, not public fields )
15.尽可能不变性(Minimize mutability )
不可变的东西容易设计与实现,而且容易避免错误,得到更多的安全。
16.组合设计优于继承设计(Favor composition over inheritance)
17.要么为继承设计并且提供文档,要么就禁止使用继承设计(Design and document for inheritance or else prohibit it )
18.接口优先于抽象类(Prefer interfaces to abstract classes )
19.接口只能用于定义类型(Use interfaces only to define types )
常量接口模式是接口的不良使用(The constant interface pattern is a poor use of interfaces. )
20.类层次优于标签类(Prefer class hierarchies to tagged classes )
21.用函数对象表示策略(Use function objects to represent strategies )
像c、c++语言中的函数指针,java8之前的匿名类,java8中的函数式编程,javascript中的闭包功能一样。
22.优先考虑静态成员类(Favor static member classes over nonstatic )
23.请不要在新代码中使用原生态类型,使用泛型(Don’t use raw types in new code )
24.清除非受检警告( Eliminate unchecked warnings)
25.列表优先于数组( Prefer lists to arrays)
26.优先考虑泛型(Favor generic types )
27.优先考虑泛型方法(Favor generic methods )
静态工具方法非常适合泛型化。
28.利用有限通配符增加api的灵活性(Use bounded wildcards to increase API flexibility )
29.优先考虑类型安全的异构容器(Consider typesafe heterogeneous containers )
30.使用枚举代替int常量( Use enums instead of int constants)
31.用实例域代替序数(Use instance fields instead of ordinals )
即枚举的ordinal 方法的返回值,我们如果要使用,必须实例域替换之。
32.用EnumSet 代替位域(Use EnumSetinstead of bit fields )
33.用EnumMap 代替序数索引(Use EnumMap instead of ordinal indexing )
34.用接口模拟可扩展的枚举(Emulate extensible enums with interfaces )
35.注解优于命名模式(Prefer annotations to naming patterns )
这个主要体现是junit框架,现在流行注解模式,而非之前很早版本的命名模式。
36.要使用Override 注解(Consistently use theOverrideannotation )
37.用标记接口定义类型(Use marker interfaces to define types )
例如Serializable 接口,定义了可序列化类型。
方法
38.校验参数的有效性(Check parameters for validity )
39.必要时进行保护性拷贝(Make defensive copies when needed )
40.谨慎的设计方法签名(Design method signatures carefully )
谨慎地选择方法的名字(Choose method names carefully)
不要过于追求提供便利的方法(Don’t go overboard in providing convenience methods )
避免过长的参数列表(Avoid long parameter lists )
对于参数类型,要优先使用接口而非类(For parameter types, favor interfaces over classes )
41.慎用重载(Use overloading judiciously )
42.慎用可变参数(Use varargs judiciously )
43.返回空的数组或集合,而非null(Return empty arrays or collections, not nulls)
44.为所有导出的api元素编写文档注释(Write doc comments for all exposed API elements)
General Programming
45.局部便变量的作用域尽可能小(Minimize the scope of local variables )
46.优先使用for-each循环语法,而非传统的for循环语法(Prefer for-each loops to traditionalforloops )
47.了解并且使用类库(Know and use the libraries )
48.如果需要精确的数字运算结果,要避免使用float和double(Avoidfloatand double if exact answers are required )
这就需要我们要正确使用BigDecimal,int, 或long 进行运算。
49.基本类型由于对应的封装类型(Prefer primitive types to boxed primitives )
50.如果其他类型比较合适,则尽量避免使用字符串(Avoid strings where other types are more appropriate )
51.要提防字符串连接的性能(Beware the performance of string concatenation )
52.通过接口来引用对应的对象(Refer to objects by their interfaces)
53.接口优于反射(Prefer interfaces to reflection )
54.谨慎的使用本地方法(Use native methods judiciously )
55.谨慎优化(Optimize judiciously)
56.遵守普遍的命名规则(Adhere to generally accepted naming conventions )
Exceptions
57.仅对对异常的情况下才使用异常(Use exceptions only for exceptional conditions )
58.对于可恢复的情况用受检异常,运行时异常用于程序错误(Use checked exceptions for recoverable conditions and runtime exceptions for programming errors)
59.避免不必要的受检异常使用(Avoid unnecessary use of checked exceptions )
60.优先使用JDK自带的标准异常(:Favor the use of standard exceptions )
61.抛出与抽象对应的异常(Throw exceptions appropriate to the abstraction )
62.每个方法所抛出的异常都需要文档化(Document all exceptions thrown by each method )
63.异常详细信息中要包含 捕获失败的信息(Include failure-capture information in detail messages )
64.努力使失败保持原子性(Strive for failure atomicity )
65.不要忽略异常(Don’t ignore exceptions )
Concurrency
66.同步访问共享可变数据(Synchronize access to shared mutable data )
67.避免过度同步(Avoid excessive synchronization )
为了避免活性失败和安全失败,在一个被同步的方法或者代码块中,永远不要放弃对客户端的控制
(To avoid liveness and safety failures, never cede control to the client within a synchronized method or block. )
通常,你应该在同步区域内做尽可能少的工作(As a rule, you should do as little work as possible inside synchronized
regions )
68.executors和tasks 的使用优于线程(Prefer executors and tasks to threads )
69.并发工具类优于wait 和notify (Prefer concurrency utilities to wait and notify )
70.线程安全文档化(Document thread safety )
71.慎用延迟初始化(Use lazy initialization judiciously )
72.不要依赖线程调度器(Don’t depend on the thread scheduler )
73.避免使用线程组(Avoid thread groups )
Serialization
74.谨慎地实现序列化接口(Implement Serializable judiciously )
75.考虑使用自定义序列化方式(Consider using a custom serialized form )
76.保护性的编写readObject 方法(Write readObject methods defensively )
77.对于实例控制,枚举类型优于readResolve (For instance control, prefer enum types to readResolve )
78.考虑使用序列化代理,而非序列化实例(Consider serialization proxies instead of serialized instance )