*1、考虑静态工厂方法(static factory method)代替构造器?!优势?不足?
服务提供者架构:
1、服务接口(Service Interface) -- 提供者实现的;
2、提供者注册API(Provider Registration API)--系统用于注册实现,让客户端访问它们;
3、服务访问API(Service Access API)--客户端用于获取服务的实例;[它是“灵活的静态工厂”,构成了服务提供者架构的基础!]
*4、服务提供者接口(Service Provider Interface)--这些提供者负责创建其服务实现的实例
[如果没有Service Provider Interface,实现就按照类名称注册,并通过反射方式进行实例化。
对于JDBC来说,
Connection就是它的服务接口,
DriverManager.registerDriver是提供注册API,
DriverManager.get Connection是服务访问API,
Driver就是服务提供者接口]
2、遇到多个构造器参数时要考虑用构造器
*3、用私有构造器or枚举类型强化Singleton属性
4、通过私有构造器强化不可实例化的能力
5、避免创建不必要的对象
*6、消除过期的对象引用
// Can you spot the "memory leak"? public class stack { private Object[] elements; private int size = 0; private static final int DEFAULT_INITIAL_CAPACITY = 16; public Stack() { elements = new Object[DEFAULT_INITIAL_CAPACITY]; } public void push(Object e) { ensureCapacity(); elements[size++] = e; } public Object pop() { if (size == 0) throw new EmptyStackException(); return elements[--size]; } /** * Ensure space for at least one more element, roughly * doubling the capacity each time the array needs to grow. */ private void ensureCapacity() { if (elements.length == size) elements = Arrays.copyOf(elements, 2*size+1); } }
BUG:“内存泄漏”,随着垃圾回收器活动的增加,或者由于内存占用的不断增加,程序性能的降低逐渐表现出来。极端情况、
会导致磁盘交换(Disk Paging),甚至导致程序报错(OutOfMemoryError)--少见!
eg:如果一个栈先是增长,再收缩,那么从栈中弹出来的对象将不会被当作垃圾回收,即使使用栈的程序不再引用这些对象,它们也
不会被回收。因为:栈内部维护着对这些对象的过期引用(obsolete reference)--即永远也不会再被解除的引用。本例中,elements
数组的“活动部分(active portion)”之外的任何引用都是过期的。活动部分指:elements中下标小于size的那些元素。
fix bug:一旦对象引用过期,需要清空这些引用。即修改pop方法,如下;
public Object pop() { if (size == 0) throw new EmptyStackException(); Object result = elements[--size]; elements[size] = null; // Eliminate obsolete reference. return result; }
好处:
1、解决BUG出现的内存长期占用,降低性能;
2、如果它们以后又被错误的解除引用,程序就会抛出NullPointerException异常,而不是悄悄继续运行下去!
/**
* 1、只要是自己管理内存,程序员就应该警惕内存泄露问题;
*
* 2、缓存;--把对象引用放到缓存中,它就很容易被遗忘掉;
[修复:只要在缓存之外存在某个项的键的引用,该项就有意义,那么就可以用WeakHashMap代表缓存!
“缓存项的生命周期是否有意义”--不容易确定。LinkedHashMap类利用它的removeEldestEntry方法!
更加复杂的缓存,必需直接使用java.lang.ref!]
*
* 3、监听器 & 其他回调
[eg:如果你实现一个API,客户端在这个API中注册回调,却没有显式地取消注册,那么除非你采取某些动作,否则
它们就会聚集。确保回调立即被当作垃圾回收的最佳方法是只保存它们的弱引用(weak reference),例如,只将它们
保存成WeakHashMap中的键。]
*
**/
7、避免使用终结方法?(即finalizer)
“不要把终结方法当作是C++析构器的对应物!(构造器)”
C++:析构器(destructors)回收一个对象所占用的资源,是构造器所必需的对应物; --也可以回收其他的非内存资源
Java:当一个对象变得不可到达时,垃圾回收机制会回收与该对象相关联的存储空间;--用try-finally实现类似工作
----------------------------
《Effective Java 》
-- Second Edition (James Gosling)
----------------------------