建和销毁对象
一般有两种方式,一种是获得本身的实例,最常用的方法就是提供一个共有的构造器。第二个方法是,类可以提供一个共有的静态工厂方法。
静态工厂方法与构造器不同的三大优势:
有名字;
调用时不用创建新的对象;
返回原来类型的任何子类型对象。
第四大优势:
在创建参数化类型实例的时候,它们使代码变得更加简洁。
服务提供者框架
三个组件:
服务接口
提供者主持API
服务访问API
可选:
服务提供者接口
静态工厂方法的缺点:
类如果不含共有的或者受保护的构造器,就不能被子类化;
它们与其他的静态方法实际没有任何区别;
遇到多个构造器参数时要考虑用构建器
常用方法:所有参数的构造器
替代方法:javaBeans,无参构造器创建对象,然后调用setter;缺点:有效性难以保证。
手工freeze对象,可以防止对象在解冻之前使用。
构造器模式,保证重叠构造器模式的安全,也能保证JavaBeans模式的可读性。
builder实例构建树
Java中传统的抽象工厂实现时Class对象,用newInstance方法充当build方法的一部分。这种用法隐含着许多问题。newInstance方法总是企图调用类的无参构造器,这个构造器甚至可能根本不存在。如果类没有可以访问的无参构造器,不会受到编译时错误。相反,客户段代码必须在运行时处理InstantiationException或者IllegalAccessException,这样既不雅观也不方便。newInstance方法还会传播由无参构造器抛出的任何一场,即使newInstance缺乏相应的throws字句。换句话说,Class.newInstance破坏了编译时的异常检查。
构建器一般要求在一开始的时候就使用,而不是由构造器或者静态工厂重构。
Singleton指仅仅被实例化一次的类。
第一种是将构造器私有,公有静态成员是个final域;缺点可能被反射攻击;
第二种是将构造器私有,公有的成员是个静态工厂方法;无性能优势,优势是灵活、与泛型相关。
第三种,枚举。最佳实践。不受反射攻击,不受多次实例化。
通过私有构造器强化不可实例化的能力。缺点是,子类没有可访问的超类构造器可调用了。因为所有的构造器都必须显示或者隐式地调用超类构造器。
避免创建不必要的对象
对于不可变类,通常可以使用静态工厂方法而不是构造器。构造器每次都会创建新的对象,而静态工厂方法不会。
将局部变量变为final静态域后,可以提高效率,但如果不是常用方法,可延迟初始化,但使实现更多复杂。
适配器、视图
适配器是指一个对象:将功能委托给一个后备对象,从而为后备对象提供一个可以替代的接口。
Long和long区别
通过维护自己的对象池来避免创建对象并不是一种好的做饭,除非池中的对象是非常重量级的。真正正确使用对象池的典型对象实例是数据库连接池。但同时也会加大代码复杂度,损坏性能。需要权衡JVM的垃圾回收期和对象池的性能。
在一定场景,是可以使用重复性创建对象,防止安全漏洞和错误。
消除过期的对象引用
清理过期的引用,可以置空。但一般没必要,不优雅。在内存管理的类中,需要清理。
只有当所有的缓存项的生命周期是由该键的外部引用而不是由值决定时,WeakHashMap才有用处。
内存泄漏的常见来源:
类自己管理内存;
缓存;
监听器和其他回调。
一般通过Heap Profier发现内存泄漏问题
避免使用终结方法
终结方法通常是不可预测的,也是很危险的,一般情况下是不必要的。
注重时间的任务不应该 由终结方法来完成。用终结方法来关闭已经打开的文件,这是严重错误,因为打开文件的描述符是一种很有限的资源。由于JVM会延迟执行终结方法,所以大量的文件会保留在打开状态,当一个程序再不能打开文件的时候,它可能会运行失败。
及时地执行终结方法正是垃圾回收算法的一个主要功能,这种算法再不同的JVM实现中会大相近庭。
Java语言规范不仅不保证终结方法会被及时地执行,而且根本就不保证它们会被执行。当一个程序终止的时候,某些已经无法访问的对象上的终结方法却根本没有被执行,这是完全由可能的。结论是:不应该以来终结方法来更新重要的持久状态。
终结方法由一个非常严重的性能损失。
finalizer
本地对等体是一个本地对象,普通对象通过本地方法委托给一个本地对象。
第二章完结