一、创建对象的两种方式

1、提供公有的构造器。

2、提供一个返回类实例的静态方法。

二、使用静态方法创建对象

优势:

1、静态工厂方法的一个好处是,与构造函数不同,静态工厂方法具有名字。产生的客户端代码更易于阅读。

//例如,构造函数BigInteger(int,int,Random)返回的BigInteger可能是素数,
BigInteger.probalePrime()的静态工厂方法,表达显然更为清楚

2、静态工厂方法的第二个好处,与构造函数不同,它们每次被调用的时候,不要求非得创建一个新的对象。对于不可变类,可以预先使用构建好的实例,或将构建好的实例缓存起来,进行重复利用,从而避免创建不必要的重复对象。

3、静态方法可以返回原返回类型的任何子类型的对象,这对于基于接口的框架提供了更大的灵活性。

4、静态方法在创建参数化类型实例的时候,可以使代码变得更加简洁。

缺点:

1、类如果不含公有的或受保护的构造器,就不能被子类化。有时这正好是优势,复合比继承更高效。

2、用于创建对象静态方法的静态方法实际上与其他静态方法没有任何区别,所以除非文档有详细的描述,否则很难找到如何实例化通过这种方法创建的类对象。

最佳实践:

1、当一个类需要多个带有相同签名的构造器时,就用静态工厂方法代替构造器,并且慎重地选择名称以便突出它们之间的区别。

2、要求客户端通过接口来引用被返回的对象,而不是通过它的实现类,即返回类型为接口而不是实现类。

3、使用惯用名称来命名静态工厂方法:

valueOf:不太严格的讲,该方法返回的实例与它的参数具有相同的值,这样的静态工厂方法实际上是类型转换方法。

of:valueOf的一种更为简洁的替代,在EnumSet中使用并流行起来。

getInstance:返回的实例是通过方法的参数来描述的,但是不能够说与参数具有同样的值。对于Singleton来说,该方法没有参数,且返回唯一的实例。

newInstance:像getInstance一样,但newInstance能够确保返回的每个实例都与其他所有实例不同。

getType:像getInstance一样,但在工厂方法处于不同的类中时使用。Type表示工厂方法所返回的对象类型。

newType:像newInstance一样,但在工厂方法处于不同的类中时使用。Type表示工厂方法所返回的对象类型。

三、避免创建重复的对象

重复使用同一个对象,而不是每次需要的时候就创建一个功能上等价的新对象,通常前者更为合适。重用方法既快速,也更为流行。如果一个对象时非可变的(immutable),那么它总是可以被重用。

String s = new String("silly");  //DON'T DO THIS!

上面的实参"silly"本身就是一个String实例,功能上等同于所有被构造函数创建的对象,如果这种用法放在一个循环或者一个被频繁调用的方法中,那么成千上万的String实例会被创建出来。

改进版本如下:

String s = "No longer silly";

这个版本只是用一个String实例,可以保证对于所有在同一个虚拟机中运行的代码,只要他们包含相同的字符串字面常量,则该对象就会被重用。

不要错误地认为本条目所介绍的内容暗示”创建对象的代价是非常昂贵的,我们应该要尽可能地避免创建对象“。相反,由于小对象的构造函数只做很少量的工作,所以,小对象的创建和回收动作非常廉价的,特别是在现代的JVM实现上更是如此,通过创建附加的对象,以使得一个程序更加清晰、简洁、功能强大,这往往也是一件好事。

反之,通过维护自己的对象池(object pool)来避免对象的创建工作并不是一个号的做法,除非池中的对象时非常重量级的。一个正确使用对象池的典型例子就是数据库连接池。建立数据库连接的代价非常昂贵的,因此重用这样的对象非常有意义。

四、清除过期的对象引用

由于java是支持垃圾回收的语言,内存泄露是很隐蔽的,举个例子:

//Can you spot the "memory leak"?
public class Stack{
private Object[] elements;
private int size = 0; public Stack(int initialCapacity){
this.elements = new Object[initalCapacity];
} public void push(Object e){
ensureCapacity();
elements[size++] = e;
} public Object pop(){
if(size==0)
throw new EmptyStackException();
return elements[--size];
} private void ensureCapacity(){
if(elements.length==size){
Object[] oldElements = elements;
elements = new Object[2*elements.length+1];
System.arraycopy(oldElements,0,elements,0,size); }
}
}

上面的程序中潜伏着一个问题,不严格地讲,这个程序有一个”内存泄露“,随着垃圾回收器活动的增加,或者出于不断增加的内存占用,程序性能的降低会逐渐表现出来。如果栈先是增长,然后再收缩,那么,从栈弹出的对象将不会被当垃圾回收,即使使用栈的客户程序不再引用这些对象,它们也不会被回收。这是因为,栈内部维护着对这些对象的过期引用(absolete reference)。所谓过期引用,是指永远也不会被解除的引用。在本例中,凡是在elements数组的”活动区域(active protion“之外的引用都是过期的,elements的活动区域是指下标小于size的那一部分。

如果一个对象引用被无意识地保留起来了,那么,垃圾回收机制不仅不会处理这个对象,而且也不会处理被这个对象引用的所有其他对象,即使只有少量的几个对象引用被无意识地保存下来,也会有很多的对象被排除在垃圾回收机制之外,从而对性能造成潜在的重大影响。

对本案例修复方法:

pubic Object pop(){
if(size==0) throw new EmptyStackException();
Object result = elements[--size];
elements[size] = null; //Eliminate obsolete reference
return result;
}

清除过期引用的另外一个好处是,如果他们在以后被错误地解除引用,则程序会立即抛出NullPointerException异常,而不是悄悄地错误地运行下去。尽可能早的检测出程序中的错误总是有益的。

Effective java笔记2--创建于销毁对象的更多相关文章

  1. Effective Java笔记一 创建和销毁对象

    Effective Java笔记一 创建和销毁对象 第1条 考虑用静态工厂方法代替构造器 第2条 遇到多个构造器参数时要考虑用构建器 第3条 用私有构造器或者枚举类型强化Singleton属性 第4条 ...

  2. [Effective Java]第二章 创建和销毁对象

    声明:原创作品,转载时请注明文章来自SAP师太技术博客( 博/客/园www.cnblogs.com):www.cnblogs.com/jiangzhengjun,并以超链接形式标明文章原始出处,否则将 ...

  3. 《Effect Java》学习笔记1———创建和销毁对象

    第二章 创建和销毁对象 1.考虑用静态工厂方法代替构造器 四大优势: i. 有名称 ii. 不必在每次调用它们的时候都创建一个新的对象:   iii. 可以返回原返回类型的任何子类型的对象: JDBC ...

  4. 《Effective Java》读书笔记 - 2.创建和销毁对象

    Chapter 2 Creating and Destroying Objects item 1:Consider static factory methods instead of construc ...

  5. 【Effective Java读书笔记】创建和销毁对象(一):考虑使用静态工厂方法代替构造器

    类可以提供一个静态方法,返回类的一个静态实例,如Boolean包装类的一个获取实例的静态方法 public static Boolean valueOf(boolean b) { return (b ...

  6. 【Java基础】创建和销毁对象

    Num1:考虑用静态工厂方法代替构造器 对于类而言,常见的方法是提供一个公有的构造器,但其实还有一种方法叫做静态工厂方法(static factory method),它只是一个返回类的实例静态方法. ...

  7. Effective Java 读书笔记之一 创建和销毁对象

    一.考虑用静态工厂方法代替构造器 这里的静态工厂方法是指类中使用public static 修饰的方法,和设计模式的工厂方法模式没有任何关系.相对于使用共有的构造器来创建对象,静态工厂方法有几大优势: ...

  8. Effective Java 学习笔记之创建和销毁对象

    一.考虑用静态工厂方法代替构造器 1.此处的静态工厂方法是指返回指为类的对象的静态方法,而不是设计模式中的静态工厂方法. 2.静态工厂方法的优势有: a.使用不同的方法名称可显著地表明两个静态工厂方法 ...

  9. 《Effective Java》读书笔记(一)之创建和销毁对象

    最近在研读<Effective Java>一书,读书不做点笔记,感觉很容易就忘掉,于是用本篇博客来记录阅读此书的笔记. 郑重声明: 由于是<Effective Java>一书的 ...

  10. Effective Java学习笔记--创建和销毁对象

    创建和销毁对象 一.静态工厂方法代替构造器 静态工厂方法的优缺点 优点: 1.可以自定义名称(可以将功能表述的更加清晰) 2.不必每次调用都创建新的对象(同一对象重复使用) 3.返回的类型可以是原返回 ...

随机推荐

  1. HIVE- SCD缓慢变化

    SCD缓慢变化维,比如一个用户维表,用户属性会变化,但是不会变化很剧烈,可能一年只会变化一两次,也不会所有用户的属性都会有变化,只有少量的数据发生变化,所以叫缓慢变化维.这种问题就是由于维度的变化所造 ...

  2. python学习笔记(mysqldb下载安装及简单操作)

    python支持对mysql的操作 已经安装配置成功python.mysql 之后根据各自电脑配置选择对应系统的MySQL-python 文件是EXE格式.打开下一步即可 下载地址博主分享下: htt ...

  3. pxcook-高效易用的自动标注工具, 生成前端代码

    1.pxcook.sketch(http://www.fancynode.com.cn/pxcook)

  4. 利用 innodb_force_recovery 解决MySQL服务器crash无法重启问题

    背景      MySQL服务器因为磁盘阵列损坏机器crash,重启MySQL服务时 报如下错误: InnoDB: Reading tablespace information from the .i ...

  5. 2017.11.17 Demo-stm8+temperature timeing control

    1Find the lab and add in project. Downtown  it from ST  official website..compile it to ensure it pa ...

  6. PostgreSQL full_page_write记录

    PostgreSQL 在 checkpoint 之后在对数据页面的第一次写的时候会将整个数据页面写到 xlog 里面. 当出现主机断电或者OS崩溃时,redo操作时通过checksum发现“部分写”的 ...

  7. Ubuntu安装最新版的nodejs

    安装玩Ubuntu的虚拟机之后安装nodejs发现npm的版本才3.5.2,这都多老了?于是Google了一下,发现是由于Ubuntu官方维护的包源太老了,想要安装nodejs的最新版,两种方法,一种 ...

  8. 设置一个严格的SESSION过期时间

    认识一:当我们需要更改session生存时间的时候通行的做法是更改php.ini文件中 1: ; Name of the session (used as cookie name). 2: sessi ...

  9. Apache中 RewriteCond 规则参数介绍 转

    摘要: RewriteCond指令定义了规则生效的条件,即在一个RewriteRule指令之前可以有一个或多个RewriteCond指令.条件之后的重写规则仅在当前URI与Pattern匹配并且满足此 ...

  10. HDU - 3949 :XOR(线性基,所有集合的不同异或和中,求从小到大第K个)

    XOR is a kind of bit operator, we define that as follow: for two binary base number A and B, let C=A ...