创建和销毁对象--effective java

前言

这是第一次学习写博客总结,很多的不足的地方,请客官多多指正,有关java的地方,多多交流

现在进入正题:

一、考虑用静态工厂方法代替构造器

这里说的工厂方法和设计模式里面的工厂方法是有区别的,

设计模式里的工厂模式是定义一个创建对象的接口,让子类选择去实现哪一个类,工厂模式让一个类的初始化延迟到其子类(设计模式之禅)。

effective java中的静态工厂只是为一个类提供一个静态方法,它本质是和当前类的其他静态方法没有区别,只是它是用来创建对象的。和构造器相比,提供的静态方法本身具有一些优势,在于易阅读,易使用,而且可以提供方法参数,并且返回的对象可以协变成子类,相当的具有灵活性。还有一个比较常见的好处是 在创建参数化类型实例的时候,和传统的构造器相比可以让代码更简洁,比较实例如下:

传统构造器: 

Map<String,List<String>>  map = new HashMap<String,List<String>>();   

可以看到,传统的构造需要在后面再写一遍,但是,提供了静态工厂方法后,这种情况就不再出现了:

静态工厂方法:

public  static <K,V> HashMap<K,V> newInstance(){

return new HashMap<K,V>();

}

静态方法构造:

Map <String,List<String>> map = HashMap.newInstance();

直接看出来,简便了很多。。。

静态方法的缺陷,如果类没有实现公有的或者受保护的构造器,那么不能实现子类化。。

二、当对象的字段过多的时候,考虑使用Builder模式

我们在创建一个对象的时候,有几种方式设置内部参数

1.直接使用构造器,一般来说,都会创建一个构造方法,将字段值放在构造器里一起创建,但是当字段过多的时候,很容易造成字段很难区分,比如:

public Demo(String field1,String field2,int field3,int field4,int field5){} 

在实际开发中,字段的命名请规范且易理解,考虑加上doc注释,不要像实例的一样。可以看到当字段很多的时候,类型基本相同的时候,很难区分各个字段,所以很容易造成错误,就像把field3 field4 field5 的字段顺序写错了,这个时候最好的结果是程序抛出运行时异常,最坏的结果程序可能还在运行中,且没有抛出错误,这时候的逻辑已经出错,而且不易发现,很难查找,但是整个程序已经偏离了我们的期望。

2.使用JavaBeans方法,通过调用默认的无参构造器,构造一个对象,之后通过提供的setter() 方法一个个的给字段添加值。

Demo demo = new Demo();

demo.setField1(field);

demo.setField2(field);

这样的方法,可以很轻松的给每一个字段赋值,但是缺陷的地方在于给每个字段赋值都是分开的操作,可能造成状态不一致。类无法仅仅通过检验构造器参数的有效性来保证一致性。试图使用处于这样不一致状态的对象,将会导致失败,这种失败与包含错误的代码大相径庭,因此调试起来也十分困难。另一点不足在于,JavaBeans模式防止了把类做成不可变的可能(15条有讲),这就需要程序员付出格外努力来确保它的线程安全。

3.使用Builder模式构造对象,既可以实现像javaBeans的给字段一一赋值,也不会像直接使用构造器一样,容易造成字段混乱。比较常见的Builder模式实例  StringBuilder类,可以查看相关源码。这里就不写代码了。StringBuilder的缺陷在于,每一次创建对象的时候都需要先创建一个它的builder对象,然后才能创建对象。

三、使用私有构造器或者枚举来强化singleton属性

对于单例模式,要保证只存在只有一个对象实例,一直以来都有很多实现方式,大多脱不出这两种范围

1,私有构造器,和静态的单例对象字段

例如:

public class SingletonDemo{

public static SingletonDemo demo = new SingletonDemo();

private SingletonDemo(){}

}

这种方法实现的单例,保证了只存在一个实例,但是有种情况是,如果特权用户用AccessibleObject.setAccess方法通过反射,可以调用当前类的私有构造器,从而创建新对象,对于抵御这种情况,需要添加判断,在第二次创建对象的时候抛出异常就可以了。

2.静态方法,私有的字段,私有的构造器

public class SingletonDemo{

private static SingletonDemo demo = new SingletonDemo();

private SingletonDemo(){}

public static SingletonDemo getInstance(){ return  demo; }

}

这种方法也保证了只有一个实例,但是不管这种方法还是前面一种方法,如果要实现Serializable接口,使得对象可序列化,就会出现问题,在反序列化的时候,readObject()方法不管显示的还是默认的,都会提供一个新的对象给我们,导致反序列化单例失败,这种情况需要提供readResolve()方法,当反序列化的时候,readResolve()方法调用时,返回当前对象的引用来替换新建对象的引用,如

public SingletonDemo readResolve(){ return demo;}

这样就可以防止对象重复创建了

3.单元素枚举----其实这是实现单例的最好方法了

在java引入枚举之后,枚举就成了单例实现的最优方式,它可以自动维护对象的个数,绝对防止重复。因为enmu的元素就是enmu的实例,当只有一个元素的时候,它就只存在一个实例,枚举的用处有很多,不懂得可以去看看基础书(java程序设计语言 阿诺德,java编程思想)

public enmu SingletonDemo{

demo;

public void doSomething(){}

}

调用的时候,直接写成SingletonDemo.demo.doSomething()就可以了

四,使用私有构造器强化不可实例化的类属性

这条其实很简单,在我们代码中,有很多类是不需要实例化的,比如以前的配置类(现在不推荐这么写,可以考虑使用枚举来写),工具类等,它只包含了静态方法,静态字段,我们不需要给它实例化,这个时候,可以使用私有构造器,防止有人不小心实例化这个类。

注意:在给予私有构造器的时候,请写doc注释,说明为什么这个类使用私有构造器,因为私有之后直接创建对象也不能子类化了

五、避免创建不必要的对象

在代码中,其实很多这样的规则我们已经在遵守了,但是这里还是写出来,警惕自己犯错

1.使用基本数据类型来替代包装器类,避免自动装箱,java引入自动装箱和拆箱操作之后,基本数据类型和包装器类之间其实很模糊了,但是优先使用基本数据类型可以有效避免创建多余对象。基本数据类型是直接将值存在堆栈中,来保证高效,但是包装器类对象是保存在堆中的

2.对于同时提供了静态工厂方法和构造器的不可变类,使用静态工厂方法,避免创建不必要对象--

3.重(chong)用已知的可变但不会修改的对象

4.维护对象池并不是好做法,除非真的是非常重量级的对象,比较常规的是数据库连接池和缓存连接池

六、消除过期引用

过期引用这点,其实牵扯到内存泄漏(指的是被无意识的保存的对象,导致内存变小),所以在类自己管理内存时,请警惕内存泄漏的问题,消除过期引用。

可以使用WeakHashMap来存储 缓存 和监听器,回调。这样在内存不够的时候gc会优先清理这部分,达到释放内存的效果。

七,避免使用finalizer方法

finalizer()一般来说很少用到,它的运行是不可预测的,gc并不保证你调用了这个方法之后,它就马上运行,而且调用这个方法会造成严重的性能损耗(java虚拟机)


结语

昨晚就花了我几个小时的时间整理,今天中午午睡时间才打完发的,第一次写很多地方都写不好,考虑不周全或者错误,不足的地方,请多多指教。来简书是因为觉得里面的博客都很简洁,不太喜欢csdn的博客样子,哈哈,可以看到后面几条我写的非常少,这些都是正常的注意下就好了,其实书上是有很多的内容,推荐去看本书,认真研读几遍帮助很大,谢谢努力的自己和努力的你~~~

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,324评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,303评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,192评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,555评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,569评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,566评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,927评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,583评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,827评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,590评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,669评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,365评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,941评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,928评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,159评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,880评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,399评论 2 342

推荐阅读更多精彩内容