Java 单身合同会被打破吗?如果是,有多少种方式?
最近,我参加了面试,她/他问了我一个问题——你的单亲班级还不到,你必须打破单亲合同,告诉我怎么做?我想了又想,但我无法想出解决办法,因为每一张支票都是为了防止违规,比如——Java 单身合同会被打破吗?如果是,有多少种方式?,java,singleton,synchronized,volatile,cloning,Java,Singleton,Synchronized,Volatile,Cloning,最近,我参加了面试,她/他问了我一个问题——你的单亲班级还不到,你必须打破单亲合同,告诉我怎么做?我想了又想,但我无法想出解决办法,因为每一张支票都是为了防止违规,比如—— 要从主存读/写的Volatile关键字 围绕方法和块同步 获取实例的静态方法 仔细检查实例是否可用 私有构造函数 以下是守则- /** * */ package com.test.singleton; /** * @author * */ public class SingletonInstance impl
/**
*
*/
package com.test.singleton;
/**
* @author
*
*/
public class SingletonInstance implements Cloneable{
private String name;
private static volatile SingletonInstance instance;
private SingletonInstance(){
System.out.println("constructor called");
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
static synchronized SingletonInstance getInstance(){
if(instance == null){
synchronized(SingletonInstance.class){
instance = new SingletonInstance();
}
}
return instance;
}
/* (non-Javadoc)
* @see java.lang.Object#clone()
*/
@Override
protected Object clone() throws CloneNotSupportedException {
// TODO Auto-generated method stub
return super.clone();
}
}
请建议是否有可能以任何方式破坏singleton契约?构造函数虽然是私有的,但可以使用反射调用:
Class<SingletonInstance> klass = SingletonInstance.class;
Constructor<SingletonInstance> defaultConstructor = klass.getConstructor();
defaultConstructor.setAccessible(true);
SingletonInstance newInstance = defaultConstructor.newInstance();
有几种情况下,您的Singleton类可能有多个实例。到目前为止,我有两点想法
private SingletonInstance(){
if(instance != null){
throw new OperationNotSupportedException("You can't create object of singletone class using this operation");
}
}
另外,通过添加readObject和readResolve方法,可以停止通过序列化和反序列化创建singleton类的多个对象,如下所示
private void readObject(ObjectInputStream inputStream) throws ClassNotFoundException, IOException {
inputStream.defaultReadObject();
instance = this;
}
private Object readResolve() {
return instance;
}
此外,您的克隆方法还应该通过一个异常
protected Object clone() throws CloneNotSupportedException {
throw new CloneNotSupportedException("Clone not supported for this class");
}
你没有具体说明“违约”是什么意思。无论如何,此代码是不正确的,当调用
getInstance()
时(有效地synchronized(null)
),它将始终抛出NPE,因此它将永远不会初始化实例。您尝试过克隆,但它返回了相同的实例?我不相信你。谢谢吉姆指出这一点。更正了代码。从术语“break the contract”开始,我的意思是无论如何都可以创建类的两个实例,@Ernest已经用反射和如何防止that@shmosel从术语“同一实例”开始,我在写问题时想到了实例的相同内容。现在我意识到措辞是不正确的。我做了问题的更正。谢谢我仍然不明白为什么不能使用克隆来解决这个问题。如果从单独的线程调用,反射仍然可以击败您的私有构造函数。您需要同步null测试,以强制volatile
的有效性。您有一个类型抛出异常
您不能在此处使用序列化,由于singletonistance
没有实现Serializable
,其private
构造函数有效地阻止了可序列化的子类。如果从单独的线程调用,反射仍然可以击败您的私有构造函数。您需要同步null测试,以强制volatile
@Bohemian的有效性,即使synchronized
在这里也没有帮助,因为您可以在第一次调用getInstance()
之前创建自己的实例,而不涉及任何并发。
protected Object clone() throws CloneNotSupportedException {
throw new CloneNotSupportedException("Clone not supported for this class");
}