笔记3~6

3、用私有构造器或者枚举类型强化Singleton属性

singleton指仅仅被实例化一次的类

1.公有静态成员是final域:

public class A{
	public static final A INSTANCE=new A();
	private A(){}
}

 2.静态工厂方法: 

public class A{
	public static final A INSTANCE=new A();
	private A(){}
        public static A getInstance(){ return INSTANCE };
}
3.包含单个元素的枚举类型

public enum A{
	INSTANCE;
}
这种方法在功能上与公有域方法相近,但是他更加简洁,无偿的提供了序列化机制,绝对防止多次实例化,即使是在面对复杂的序列化或者反射攻击的时候。

4、通过私有构造器强化不可实例化的能力

企图通过将类做成抽象类来强制该类不可被实例化是行不通的,该类可以被子类化,并且该子类可以被实例化。这样做容易误导用户,以为这种类是专门为了继承而设计的。

简单的确保类不会被实例化的方法:

由于只有当类不包含显式的构造器的时候,编译器才会生成缺省的构造器,因此我们只需要让这个类包含私有构造器。

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

以下方法isBabyBoomer检查person是否在1946-1965间出生

public class Person{
	//未初始化
	private final Date birthDate;
	
	public boolean isBabyBoomer(){
		Calendar gmtCal=Calendar.getInstance(TimeZone.getTimeZone("GMT"));
		gmtCal.set(1946,Calendar.JANUARY,1,0,0,0);
		Date boomStart=gmtCal.getTime();
		gmtCal.set(1965,Calendar.JANUARY,1,0,0,0);
		Date boomEnd=gmtCal.getTime();
		return birthDate.compareTo(boomStart)>=0&&birthDate.compareTo(boomEnd)<0;
	}
}
每次调用都会新建一个Calendar,一个timezone,两个Date实例。以下使用 静态的初始化器

public class Person{
	//未初始化
	private final Date birthDate;
	static {
		Calendar gmtCal=Calendar.getInstance(TimeZone.getTimeZone("GMT"));
		gmtCal.set(1946,Calendar.JANUARY,1,0,0,0);
		Date boomStart=gmtCal.getTime();
		gmtCal.set(1965,Calendar.JANUARY,1,0,0,0);
		Date boomEnd=gmtCal.getTime();
	}
	public boolean isBabyBoomer(){
		return birthDate.compareTo(boomStart)>=0&&birthDate.compareTo(boomEnd)<0;
	}
}
改进后只在初始化的时候才创建实例,而不是在每次调用isBabyBoomer的时候都创建的实例。

如果改进后的person类被初始化了,它的的isBabyBoomer方法却永远不会被调用,那就没有必要初始化boomStart了,通过延迟初始化(lazily Initializing)即把对这些域的初始化延迟到第一次被调用的时候进行,则有可能消除这些不必要的初始化工作,但是不建议这么做。这样做会使方法的实现更加复杂,从而无法将性能显著提高到超过已经达到的水平。

6、消除过期的对象引用

“内存泄漏“的例子

public class Stack{
	private Object[] elements;
	private int size=0;
	private static final int DEFAULT_INITIAL_CAPACITY=16;
	
	public Stack(){
		elements=new Object[DEFAULT_INITIAL_CAPACITY];
	}
	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)
			elements=Arrays.copyOf(elements, 2*size+1);
	}
}
栈中弹出来的对象将不会被当做垃圾回收,即使使用栈的程序不再引用这些对象,它们也不会被回收。这是因为栈内部维护着对这些对象的过期引用(obsolete reference)。

改进:

<pre name="code" class="java">public Object pop(){
<span style="white-space:pre">	</span>if(size==0)
		throw new EmptyStackException();
	Object result =elements[--size];
	elements[size]=null;
	return result;
}

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



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值