1.考虑使用静态工厂方法替代构造方法
优势:
- 静态工厂方法相比构造器有名称
- 使用静态工厂方法, 不比在每次调用的时候都创建一个新对象
- 使用静态工厂方法, 可以返回原返回类型的任何子类型的对象
- 使用静态工厂方法, 在创建参数化类型示例的时候可以使代码更加简洁
缺点:
- 类如果不含有共有的或是受保护的构造器, 就不能被子类化
- 它们与其他静态方法实际上没有任何区别
静态工厂方法的命名:
valueOd, of, getInstance, newInstance, getType, newType
补充: 静态工厂方法返回的对象所属的类, 在编写包含该静态工厂的方法的类时可以不必存在, 这种灵活的静态工厂方法构成了服务提供者框架的基础
服务提供者框架(Service Provider Framwork)
- 服务接口, 提供者要实现的接口
- 提供者注册API, 系统用来注册实现, 让客户端访问的
- 服务访问API, 是客户端用来获取服务的实例的
服务提供者接口(可选), 提供者负责创建其服务实现的实例 ```java public interface Provider {
Service newService(); }
public interface Service {
}
public class Services {
private static final Map<String, Provider> providers = new ConcurrentHashMap<String, Provider>();public static final String DEFAULT_PROVIDER_NAME = "<def>";private Services() {}public static void registerDefaultProvider(Provider p) {registerProvider(DEFAULT_PROVIDER_NAME, p);}private static void registerProvider(String name, Provider p) {providers.put(name, p);}public static Service newInstance() {return newInstance(DEFAULT_PROVIDER_NAME);}public static Service newInstance(String name) {Provider p = providers.get(name);if (p == null) {throw new IllegalArgumentException("No provider registered with name: " + name);}return p.newService();}
}
<a name="f8XMd"></a>## 2.遇到多个构造器参数是要考虑用构建器简言之, 方便拓展大量的可选参数.<br />构造器示例:```java/*** @author gavin* @date 2020-07-02*/public class DemoBuilder {private int certainArg1;private int certainArg2;private int unCertainArg3;private int unCertainArg4;private int unCertainArg5;private DemoBuilder(Builder builder) {certainArg1 = builder.certainArg1;certainArg2 = builder.certainArg2;unCertainArg3 = builder.unCertainArg3;unCertainArg4 = builder.unCertainArg4;unCertainArg5 = builder.unCertainArg5;}public static class Builder {// 必须的参数private final int certainArg1;private final int certainArg2;// 非必须的参数, 初始化给默认值private int unCertainArg3 = 0;private int unCertainArg4 = 0;private int unCertainArg5 = 0;public Builder(int certainArg1, int certainArg2) {this.certainArg1 = certainArg1;this.certainArg2 = certainArg2;}public Builder unCertainArg3(int val) {unCertainArg3 = val;return this;}public Builder unCertainArg4(int val) {unCertainArg4 = val;return this;}public Builder unCertainArg5(int val) {unCertainArg5 = val;return this;}public DemoBuilder build() {return new DemoBuilder(this);}}}
使用:
@Testpublic void testDemo(){DemoBuilder demo = new DemoBuilder.Builder(1, 2).unCertainArg3(3).unCertainArg4(4).unCertainArg5(5).build();}
3.用私有构造器或者枚举类型强化Singleton属性
4.通过私有构造器强化不可实例化的能力
5.避免创建不必要的对象
- 对于同时提供了静态工厂方法和构造器的不可变类, 通常可以使用静态工厂方法而不是构造器, 以避免创建不必要的对象, 例如, Boolean.valueOf(String), 优先于Boolean(String).
- 重用那些已知的不会被修改的可变对象, 可以在类初始化的时候只创建实例一次, 比如正则的Pattern
- 优先使用基本类型而不是装箱基本类型, 要当心无意识的自动装箱
示例: 下面代码构造了大约2的31次方个多余的Long实例, 每次往Long sum中增加long时构造了一个实例
/*** 计算所有int数的值* @param args*/public static void main(String[] args) {Long sum = 0L;for (long i = 0; i < Integer.MAX_VALUE; i++) {sum += 1;}System.out.println(sum);}
6.消除过期的对象引用
- 只要类是自己管理内存, 程序员就应该警惕内存泄漏问题, 一旦元素被释放掉, 则该元素中包含的任何对象引用都应该被清空
示例代码: 下面的栈实现, 若栈先增长, 后收缩; 栈还维护者>size的元素的过期引用, 实际上这些元素不会被访问到, 这导致了程序的内存泄露
/*** 栈实现** @author gavin* @version 2020/7/5*/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];}private void ensureCapacity() {if (elements.length == size) {elements = Arrays.copyOf(elements, 2 * size + 1);}}public void push(Object e) {ensureCapacity();elements[size++] = e;}public Object pop() {if (size == 0) {throw new EmptyStackException();}return elements[--size];}}
修复方案: 一旦对象引用已经过期, 只需清空这些引用即可; 且清空了过期引用, 若以后他们被错误的解除引用, 程序会立即抛出NPE, 而不是悄悄的错误运行下去.
public Object pop() {if (size == 0) {throw new EmptyStackException();}Object element = elements[--size];// 出栈则清除引用elements[size] = null;return element;}
- 内存泄漏的另一个常见来源是缓存, 缓存注意维护过期时间
- 内存泄漏的第三个常见来源是监听器以及其他回调.
如果你实现了一个API, 客户端在这个API种注册回调, 却没有显示的取消注册, 那么除非你采取某些动作, 否则它们就会积聚, 确保回调立即被当做垃圾回收的最佳方法时只保存它们的弱引用, 例如, 只将它们保存成WeakHashMap中的键.
7.避免使用终结方法
终结方法是不可预测的, 也是很危险的, 一般情况下是不必要的.
Java语言规范不仅不保证终结方法会被及时的执行, 而且根本就不保证它们会被执行, 不应该依赖终结方法来更新重要的持久状态.
