java單例之enum實現方式


傳統的兩私有一公開(私有構造方法、私有靜態實例(懶實例化/直接實例化)、公開的靜態獲取方法)涉及線程安全問題(即使有多重檢查鎖也可以通過反射破壞單例),

目前最為安全的實現單例的方法是通過內部靜態enum的方法來實現,因為JVM會保證enum不能被反射並且構造器方法只執行一次。

實現方法如下:

/**
 * 使用枚舉的單例模式
 *
 * @author yzl
 * @see [相關類/方法](可選)
 * @since [產品/模塊版本] (可選)
 */
public class EnumSingleton{
    private EnumSingleton(){}
    public static EnumSingleton getInstance(){
        return Singleton.INSTANCE.getInstance();
    }
    
    private static enum Singleton{
        INSTANCE;
        
        private EnumSingleton singleton;
        //JVM會保證此方法絕對只調用一次
        private Singleton(){
            singleton = new EnumSingleton();
        }
        public EnumSingleton getInstance(){
            return singleton;
        }
    }
}

測試方法:

public static void main(String[] args) {
    EnumSingleton obj1 = EnumSingleton.getInstance();
    EnumSingleton obj2 = EnumSingleton.getInstance();
    //輸出結果:obj1==obj2?true
    System.out.println("obj1==obj2?" + (obj1==obj2));
}

 

擴展應用,觀察下面的例子

public class Test{
  //初始化一些東西
  static{
    
   }
}

這是一個很常見的類內部的靜態資源初始化的寫法(其實也就是單例的另外一種表現-只執行一次),但是將代碼都寫在static塊下會看起來很不優雅,可以利用上面的enum單例模式來進行初始化操作。

見例子:

 

import java.util.ArrayList;
import java.util.List;

/**
 * 初始化的優雅實現
 * 可以在static處調用,
 * 也可以在普通方法里調用,都保證只初始化一次
 * 
 * 當然將enum塊的代碼直接放到StaticInitTest類的private static 方法里做也是可以的
 *
 * @author yzl
 * @see [相關類/方法](可選)
 * @since [產品/模塊版本] (可選)
 */
public class StaticInitTest {
    private static List<Integer> dataList = null;
    
    static{
        dataList = Singleton.INSTANCE.init();
    }
    
    /**
     * 
     * 單例模式來填充數據
     *
     * @author yzl
     * @see [相關類/方法](可選)
     * @since [產品/模塊版本] (可選)
     */
    private static enum Singleton {
        INSTANCE;
        private List<Integer> list;
        
        private Singleton(){
            fillData();
        }
        /**
         * 
         * 初始化數據
         *
         * @see [相關類/方法](可選)
         * @since [產品/模塊版本](可選)
         */
        private void fillData(){
            list = new ArrayList<Integer>(5);
            for(int i =1; i<6; i++){
                list.add(i);
            }
        }

        /**
         * 
         * 初始化的入口
         *
         * @see [相關類/方法](可選)
         * @since [產品/模塊版本](可選)
         */
        public List<Integer> init(){
            return list;
        }
    }
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM