单身合同能否被打破?如果是,有多少种方式?

时间:2018-02-11 06:09:11

标签: java singleton synchronized volatile cloning

最近我出现在面试中,她/他问我这个问题 - 你有单身课程以下,你必须打破单身合同,告诉我该怎么做?我想到并想到了方法,但我无法达到解决方案,因为每个检查都是为了防止违规行为,如< - p>

  1. 从主存储器读/写的易失性关键字
  2. 围绕方法同步并阻止
  3. 获取实例的静态方法
  4. 仔细检查实例是否可用
  5. 私人构造函数
  6. 以下是代码 -

    /**
     * 
     */
    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();
        }
    
    }
    

    请建议是否可以以任何方式违反单身合同?

2 个答案:

答案 0 :(得分:1)

有几种情况,您的Singleton类可能有多个实例。截至目前,我脑子里有2分。

  1. 通过反射调用私有构造函数。
  2. 通过序列化和反序列化。
  3. 这是通过私有构造函数调用停止创建对象的方法。

    private SingletonInstance(){
              if(instance != null){
                    throw new OperationNotSupportedException("You can't create object of singletone class using this operation");
             }
           }
    

    此外,您可以通过添加readObject和readResolve方法,通过序列化和反序列化来停止创建单个类的多个对象。

    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");
        }
    

答案 1 :(得分:0)

构造函数虽然是私有的,但可以使用反射来调用:

Class<SingletonInstance> klass = SingletonInstance.class;
Constructor<SingletonInstance> defaultConstructor = klass.getConstructor();

defaultConstructor.setAccessible(true);
SingletonInstance newInstance = defaultConstructor.newInstance();

这样就可以创建多个实例。

为了防止这种情况,它应该包含自己的检查,如有效的java中所示:

private SingletonInstance(){ 
    if(instance != null)
        throw new IllegalStateException(); //or some other exception
    System.out.println("constructor called"); 
}