创建和销毁对象(内功篇)

第1条:考虑用静态工厂方法替代构造函数

静态方法的好处
1. 与构造函数不同,静态工厂方法具有名字。如果以个构造函数的参数并没有确切的描述被返回的对象,那么选用适当的名字的静态工厂可以试一个类更易于使用,并且相应的客户代码更易于阅读。因为静态工厂方法自己有名字,所以他们没有构造函数那样的限制,对于给定的原型的特征,可以有不止一个静态工厂方法,如果以个类看起来需要多个构造函数,并且他们的原型特征相同,那么你应该考虑用静态工厂方法来代替其中一个或者多个构造函数,并且慎重的选择他们的名字以便明显的标示出他们的不同。
2. 与构造函数不同,他们的每次被调用的时候,不要求非要创建一个新的对象。静态工厂方法可以为重复的调用返回同一个对象。
3. 与构造函数不同,他们可以返回一个原返回类型的子类型的对象。这样我们的选择被返回对象的类型时就有了更大的灵活性。

静态方法的缺点:
1. 类如果不含有公有的或者受保护的构造函数,就不能被子类化,例如,想要子类化Collecions中的任何一个方便的实现类,是不可能的,然而这也许会因祸得福,因为它会鼓励程序员使用复合结构,而不是继承。
2. 他们与其他任何静态方法没有任何区别。在API文档中,他们不会像构造函数那样被明确标示出来,而且,静态工厂方法代表了一种对规范的背离。
静态工厂方法的量个名字已经变得很流行:
 valueOf----不太严格的讲,该方法返回的实力与他的参数具有同样的值,使用这个名字的静态工厂方法是一些非常有效的类型转换操作符。
 getInstance----返回的实例是由该方法的参数来描述的,但是不能够说与参数具有同样的值。对于singleton的情形,改方法返回唯一的实例。
总得来说,静态工厂方法和公有的构造函数都有他们各自的用途,我们需要理解他们各自的长处,避免一上来就构造函数,而不考虑静态工厂方法。因为静态工厂通常更加适合。如果你正在权衡这两种选择,又没有其他因素强烈的影响你的选择,那么你最好还是简单的使用构造函数,毕竟他们语言提供的规范。

第2条:使用私有构造函数强化singleton属性
Singleton通常被用来代表那些本质上具有唯一性的系统组件,比如视频显示或者文件系统。实现singleton有两种方法。这两种方法都要把构造函数保持似有,并且提供一个静态成员,以便允许客户能够访问该类唯一的实例。在这一种方法中,公有的静态成员是一个final域:
Public class Elvis{
Public static  final  Elvis INSTANCE=new Elvis();
Private   Elvis(){}
}

Public class Elivs{
Private static final Elvis INSTANCE=new Elvis();
Private   Elvis(){}
Public static Elvis getInstance(){
Return INSTANCE;
}
}
第一种的好处在于,组成类的成员的声明很清楚的表明了这个类的是一个singleton:公有的静态域是final的,所以该域总是包含相同的对象引用。第一种方法可能在性能上稍微领先。
第二种方法的主要好处在于,它提供了灵活性:在不改变API的前提下,允许我们改变想法,把该类做成singleton.或者不做成singleton.singleton的静态工厂方法返回该类的唯一实例,但是,它也很容易被修改,比如说,为每个调用该方法的线程返回一个唯一的实例。总言而之,如果你确信该类将永远是一个singleton,那么使用第一种方法是有意义的。如果你希望保留一点余地,那么请使用第二种方法。
对象序列化seializeble,仅仅在声明中加上implements Serializeble是不够的,为了维护唯一性,你必须也要提供一个readResolve方法,否则得话,一个序列化的对象每次反序列化得时候,都会创建一个新的实例,比如说,在我们的例子中,就会产生一个假冒的Elvis,为了防止这种情况,在Elvis类中加入下面的readRelove方法:
Private Object readResolve()throws ObejctStreamExcetion{
Return INSTANCE;
}

第3条:通过似有构造函数强化不可实例化的能力
偶尔情况下,你可能会编写出只包含静态方法和静态域的类。一些工具类就是这样,这样的类不希望被实例化,对它进行实例化没有任何意义,所以,我们只要让这个类包含单个显式的私有构造函数,则它就不可被实例化了

第4条:避免创建重复的对象
重复使用同一个对象,而不是每次需要就创建一个 功能等价的新对象,通常前者更为合适。重用方式既快速,也更为流行。如果一个对象是非可变的,那么他总是可以被重用。对于同时提供了静态工厂方法和构造函数的非可变类,你通常可以利用静态方法而不是构造函数,以避免创建重复对象。例如,静态工厂方法Boolean.valueOf(String)几乎总是优先于构造函数Boolean(String)。
不要错误的任务“创建对象的代价是昂贵的,我们应该要尽可能的避免创建对象”。相反,由于小对象的构造函数只做很少量的工作,所以,小对象的创建和回收动作是非常廉价的。
反之,通过维护自己的对象池来避免对象的创建工作并不是一个很好的做法,除非池中的对象是非常重量级的,一个正确使用对象池的典型例子就是数据库连接池。然而一般而言,维护自己的对象池会吧代码弄的很乱,增加内存占用,并且还会损害性能。JVM的垃圾回收器,其性能很容易就会超过轻量级对象池的性能。
注意,在提倡使用保护性拷贝的场合,因重用对象而肇事的代价要远远大于因创建对象而招致的代价,在要求保护性的情况下却没有实施保护性拷贝,将会导致潜在的安全漏洞;而不必要的创建对象仅仅影响程序的风格和性能。

第5条:消除过期的对象引用
垃圾回收机制很容易让人刘翔这样的印象,认为自己不再需要管理内存的事情了,实际上,这是不正确的。一般而言,只要一个类自己管理它的内存,程序员就应该警惕内存泄露的问题,一旦以个元素被释放掉,该元素中包含的任何对象引用应该要被清空。
内存泄露的另一个常见来源是缓存,一旦你把一个对象引用放入一个缓存中,他就很容易被遗忘掉,从而使得它不再游泳之后很长一段时间内仍然留在混村中,对于这个问题,,有两种可能的解决方案,如果你正巧实现这样的缓存:只要缓存之外存在某个条目的键的引用,该条目就有意义,那么你可以使用WeakHashMap来代表缓存;当缓存的条目过期之后,他们会自动删除。而更为常见的情形是,“被缓存的条目是否有意义”的周期并不很容易确定,其中的条目会在运行的过程中变得越来越没有价值。在这样的iqngkuang下,缓存应该时不时的清除掉无用的项目,这样工作可由一个后台线程来完成,或者加入新的条目的时候做清理工作。LRU算法等等。在1.4中,LinkedHashMap类,利用它的removeEldestEntry方法可以很容易实现后一种方案。

第6条:避免使用终结函数
终结函数通常是不可预测的,一般情况下是不必要的,因为运行垃圾回收是一个很低级的线程,往往很难确定垃圾回收执行的时间,所以终结函数finalizer函数的运行也存在不确定性。前往不要再finalizer函数内写关闭文件或数据库链接这类的语句,或者是必须做得事情不适合在finalizer中来完成。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值