注册 登录  
 加关注
查看详情
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

清风幻影的博客

Where there is love, I will be there.

 
 
 

日志

 
 
关于我

同是天涯沦落人,相逢何必曾相识. 天生我材必有用,千金散尽还复来. 天若有情天亦老,人间正道是沧桑. 月影西斜人已去, 堤上梅花情依旧, 此情故已成追忆, 美人如玉夜留香

effective java读后感1(1-5点)  

2011-10-14 16:58:35|  分类: java_5 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

转http://www.blogjava.net/stone2083/archive/2008/02/19/180550.html
effective java中提供了57条建议。针对这些建议,我谈谈自己的理解。

1.考虑用静态工厂方法代替构造函数
静态工厂方式相比于构造函数的两个优点:
1)可以有符合自己身份的方法名,方便客户端代码的阅读
2)调用的时候,不要求创建一个新的实例。可以返回缓存实例,或者singleton实例等

静态工厂方法的最大缺点:
如果类中没有public或者protected的构造函数,使用静态工厂方法的方式得到实例,那么这个类就无法被继承。
比如
public class Demo {
    
private static Demo demo = new Demo();

    
public static Demo getInstance() {
        
return demo;
    }

    
private Demo() {
    }
}
那么这个类就无法被继承。
(当然,鼓励使用组合,而不是继承)

在spring没有流行起来的那些日子里,我大量使用工厂方法,但是使用spring等ioc容器后,这一切都是交给容器去处理了。或许,在客户端代码中,工厂模式会因为这些ioc的出>现,而遭受淘汰。


2.使用私有构造函数强化singleton属性

一旦存在public或者protected的构造函数,那么无法保证一个类,一定是sinleton的。因为无法得知客户端代码是使用构造函数,还是同构静态方法去得到类实例。所以对于一个严格要求singleton的类,那么其构造函数必须是私有的。
既然说到singleton了,那么顺便说下几个常见的创建方法
1)
/**
 * 优点:简单,而且可以确保一定是singletion实例
 * 缺点:类加载时,就会初始化实例,不能做到延迟初始化。
 
*/
public class Demo {
    
private static final Demo demo = new Demo();

    
public static Demo getInstance() {
        
return demo;
    }

    
private Demo() {
    }
}
2)
/**
 * 优点:lazy load(延迟初始化实例),提高效率
 * 缺点:多线程情况下,可能初始化多份实例
 
*/
public class Demo {
    
private static Demo demo = null;

    
public static Demo getInstance() {
        
if(demo  == null ) {
            demo 
= new Demo();
        }
        
return demo;
    }

    
private Demo() {
    }
}
3)
/**
 * 优点:lazy load(延迟初始化实例),提高效率
 *              采用double check并且同步的方式,理论上确保在多线程的应用场景中,也只创建一份实例
 * 备注:(涉及到jvm的实现,在实际应用中,也可能生成多份实例,但是几率是相当地低)
 
*/
public class Demo {
    
private static Demo demo = null;

    
public static Demo getInstance() {
        
if(demo  == null ) {
            
synchronized(Demo.class)  {
                
if(demo == null) {
                    demo 
= new Demo();
                }
            }
        }
        
return demo;
    }

    
private Demo() {
    }
}


3.使用私有构造函数强化不可实例化能力
咋一看这个标题,觉得不可思议,居然让类不具备实例化能力。但是确实也有一些应用场景,比如一些util类,就不需要实 例化。但是有很大的副作用,就是类无法被继承。所以换成我,就算是util类,我还是会保留其public的构造函数的。客户端就算要实例化这些 util,也无伤大雅。


4.避免创建重复对象
一般情况下,请重复使用同一个对象,而不是每次需要的时候创建一个功能上等价的新对象。这主要是为了性能上的考虑,何况在一般的应用场景下,确实没有必要去重复创建对象。当然有时候为了OO设计考虑,也不特别排斥创建重复的小对象。
需要明确的是,避免创建重复的对象,请不要产生一个误区就是:创建对象的成本非常昂贵。事实上,创建小对象的开销是非常小的,而且现在的jdk gc对于小对象的GC代价也是非常廉价(在之后的日子里,我会针对sun jdk gc,做一次介绍)。比如在做Swing开发的时候,会创建很多EventListener对象,比如在Spring Framework中,就创建很多匿名内隐类对象实现类似ruby等动态语言的Closure(闭包)。
但是也不可否认的是,创建大对象,对大对象的GC 的开销是比较大的。比如初始化一个对象的时候,需要加载10m的文件内容到内存;创建数据库连接对象等等,在这些场景下,创建的开销是相当昂贵了,一定要尽可能避免重复对象的创建(除非特殊需求)。
对于这些大对象,一般采用singleton模式,cache,或者object pool等方式,避免重复的创建。至于采用具体什么方式,需要根据具体的应用场景来决定了。


5.消除过期对象的引用
为什么要这么做?其实只要理解“java内存泄露”这个概念就可以了。java中的内存泄漏不同于C++中的内存泄漏。 C++是需要程序员手工管理内存的语言,创建一个对象,用完之后,需要手工删除这个对象。而java不一样,jdk gc替程序员做了这件事情,一旦对象失去了引用之后,jdk gc就会自动回收这个对象。
为了避免java中的内存泄漏,只需要知道一点就可以:对于无用的对象,必须消除对这个对象的引用。
怎么消除对象的引用呢?难道需要手工设置“object=null;”,那么一旦程序中到处充斥着这样的代码,将会是一件非常恶心的事情,严重影响程序的阅读性。
正确的做法是,每个定义的变量给予最紧凑的作用域,一旦对象结束生命周期,自然就消除了对其的引用。
当然在必要的场合,也不反对采用清空对象引用的方法,但是不推荐。
内存泄漏的症状不能在短时间内反应出来,往往是在程序运行一段时间,一天,一周,一个月,甚至一年,才逐渐显现的,一个经验丰富的程序员,也不能确保其代 码一定不存在内存泄漏的问题。检查内存泄漏问题,往往需要借助工具,heap profile,比如jprofile等等。在linux下面,可以使用jps jstat jinfo jmap等命令去观察。
  评论这张
 
阅读(424)| 评论(0)
推荐 转载

历史上的今天

在LOFTER的更多文章

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2018