在《秒懂java,对于创建一个java对象,你真的会吗?》一文中,讲述了java如何创建一个对象以及如何更优雅的创建对象。此外,java里还有一种比较特殊的创建对象的方式:私有构造器创建对象。
java私有构造器
私有构造器就是一个类的构造方法的访问权限定义为private,它只能被包含它的类自身所访问,而无法在类的外部调用,故而可以阻止对象的生成。这就好比现代社会的一夫一妻制,这个private的私有构造方法就类似这种约束制度,类就是一大老爷们,私有构造方法创建的对象就好比是这个大老爷们明媒正娶的老婆。
package cn.lovecto.test;
/**一夫一妻制*/
public class Monogamy {
/**一个丈夫只允许有一个妻子*/
public static class Husband{
/**妻子的名字*/
private String wife;
/**丈夫唯一的妻子(一个husband只能有一个wife实例)*/
private static final Husband WIFE = new Husband("wife");
/**私有的构造方法时强有力的制度约束*/
private Husband(String wife){
this.setWife(wife);
}
/**在公共场合,是可以看到这个丈夫漂亮的老婆的*/
public static Husband getInstance(){
return WIFE;
}
/**妻子可以为丈夫生儿育女*/
public Object baby(){
return wife + "'s baby";
}
public String getWife() {
return wife;
}
public void setWife(String wife) {
this.wife = wife;
}
}
}
在上面的内部类Husband就是一个只有私有构造器的类。我们通常使用私有构造器这种手段来实现单例(Singleton)。Singleton通过将构造方法限定为private避免了类在外部被实例化,在同一个虚拟机范围内,Singleton的唯一实例只能通过getInstance()方法访问。
java反射对私有构造器的访问
本来一夫一妻制度挺好的,但是有时候丈夫经常在外面应酬,看见其他漂亮的女人也难免心动,经不住诱惑,于是就会出轨,就会有情人,就会有小三小四甚至还有了小孩。私有构造器的约束本来也是挺好的,但也不能完全做到一个类只有一个实例,我们可以通过Java反射机制来实现对类的私有构造方法的访问从而创建新的对象:
//一夫一妻制度下
System.out.println(Husband.getInstance().baby());
//反射机制导致丈夫出轨找到情人还生了孩子
Class clazz = Husband.class;
Constructor constructor = clazz.getDeclaredConstructor(new Class[]{String.class});
constructor.setAccessible(true);
Husband lover = (Husband)constructor.newInstance(new Object[]{"lover"});
System.out.println(lover.baby());
java私有构造实现单例多线程问题
上面的例子中,类加载的时候就会直接new一个静态对象出来,在不使用同步锁的情况下实现了线程安全,当系统中这样的类较多时,会使得启动速度变慢。由于一个男孩子不可能一出生就立刻找老婆,只有等到他达到法定结婚年龄后才会娶妻生子。到达法定结婚年龄从我们系统的角度叫“适时加载”,就是在第一次使用的时候才初始化该类对象:
/**一个丈夫只允许有一个妻子*/
public static class Husband{
/**妻子的名字*/
private String wife;
/**丈夫唯一的妻子(一个husband只能有一个wife实例)*/
private static Husband WIFE;
/**私有的构造方法时强有力的制度约束*/
private Husband(String wife){
this.wife = wife;
}
/**对获取实例的方法进行同步*/
public static synchronized Husband getInstance(){
if(WIFE == null){
WIFE = new Husband("wife");
}
return WIFE;
}
}
上面的代码中,getInstance方法被锁住,如果调用这个方法的线程很多,将导致很多线程阻塞在这里,粒度有点大,我们只需要锁住创建对象的那部分即可,下面是改进的getInstance方法:
public static Husband getInstance(){
if(WIFE == null){
synchronized (Husband.class) {
WIFE = new Husband("wife");
}
}
return WIFE;
}
总结
java私有构造器是实现单例(Singleton)模式的有效形式,但在使用过程中要考虑多线程问题以及合适的时机创建对象。单例模式就类似于一夫一妻制,适时加载对象就好比要达到婚育年龄才允许结婚。看完这篇《秒懂java,java私有构造器与一夫一妻制》, 你是否get到了呢?