<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    I want to fly higher
    programming Explorer
    posts - 114,comments - 263,trackbacks - 0
    第三條:用私有構造器或者枚舉類型強化Singleton屬性
       
         1.Singleton指僅僅被實例化一次的類。Singleton通常被用來代表那些本質上唯一的系統組件,如窗口管理器或者文件系統。使類稱為Singleton會使它的客戶端調試變的十分困難,因為無法給Singleton替換模擬實現,除非它實現一個充當其類型的接口.
         2.在Java1.5發行版本之前,實現Singleton有兩種方法。這兩種方法都要把構造器保持為私有,并導出公有的靜態成員,以便客戶端能夠訪問該類的唯一實例,以便允許client能夠訪問該類的唯一實例。
         3.第一種方法中,公有靜態成員是個final域:
          public class Singleton1
       {
        public static final Singleton1 INSTANCE = new Singleton1();
        //私有改造函數
        private Singleton1()
        {
        }
        //其他方法實現
        public void otherMethod()
        {
         //...
        }
       }
       私有構造器僅被調用一次,用來實例化公有的靜態final域Singleton1.INSTANCE.由于缺少公有的或者受保護的構造器,所以保證了Singleton1的全局唯一性。一旦其被實例化,只會存在一個實例,不多也不少??蛻舳说娜魏涡袨槎疾粫淖冞@一點。
           :享有特權的client可以借助AccessibleObject.setAccessible方法,通過反射機制調用私有構造器。如果要抵御這種攻擊,需要修改構造器,讓其在創建第二個實例的時候拋出異常。
          4.在實現Singleton的第二種方法中,公有的成員是個靜態工廠方法:
       public class Singleton2
       {
        //私有static Instance
        private static final Singleton2 INSTANCE = new Singleton2();
        
        //私有構造函數
        private Singleton2()
        {
        }
        
        //獲取單例方法
        public static Singleton2 getInstance()
        {
         return INSTANCE;
        }
        
        //其他方法
        public void otherMethod()
        {
         //...
        }
       }
       對于靜態方法Singleton2.getInstance的所有調用,都會返回同一個對象引用,所以永遠不會創建其他的實例。
       :上述利用反射的提醒依然適用。
          5.公有域方法的好處在于,組成類的成員的聲明很清楚的表明了這個類是一個Singleton(final),公有的靜態域是final的,所以該域將總是包含相同的對象引用。公有域方法在性能上不再有任何優勢:現在JVM實現幾乎都能都將靜態工廠方法的調用內聯化。
          注:內聯:指函數在被調用的地方直接展開,編譯器在調用時不用像一般函數那樣,參數壓棧,返回時參數出棧以及資源釋放等,這樣提高了程序執行速度.
          6.工廠方法的優勢在于,它提供了靈活性:在不改變其API的前提下,我們可以改變該類是否為Singleton的想法。工廠方法返回該類的唯一實例,不過它可以很容易被修改,如改成為每個調用該方法的線程返回一個唯一的實例。
           第二個優勢在于與泛型有關。
           這些優勢之間通常不相關,public域的方法比較簡單.
          7.以上的兩種的其中一種方法實現的Singleton類如果變成是可序列化的Serialiazble,僅僅在聲明加上implements Serializable是不夠的。為了維護并保證Singleton,必須聲明所有實例都是瞬時transient的,并提供 一個readResolve方法。否則每次反序列化一個序列化的實例時,都會創建一個新的實例。即會導致一個假冒的對象。為了防止這種情況,需要在單例類中增加readResolve方法->
           注:readResolve方法用來重新指定反序列化得到的對象.
       private Object readResolve()
       {
        return INSTANCE;
       }
          8.從Java 1.5發行版本起,實現Singleton還有第三種方法。只需編寫一個包含單個元素的枚舉類型。
      public Enum Singleton3
      {
       INSTANCE;
       
       public void otherMethod()
       {
       }
      }
          這種方法在功能上與公有域方法相近,但是其更加簡潔,無償提供了序列化機制,絕對防止多次實例化,即使是面對復雜的序列化或者反射攻擊的時候。 雖然這種方法還沒有廣泛使用,但是單元素的枚舉類型已經成為實現Singleton的最佳方法。
          注:用反射調用私有構造函數:報錯:
           Exception in thread "main" java.lang.IllegalArgumentException: Cannot reflectively create enum objects.
           ps:枚舉真心不錯.

    部分源碼:
    package com.book.chap2.singleton;

    import java.lang.reflect.Constructor;

    /**
     * 
     * 單例實現1
     * <p>
     * 公有靜態成員是個public final域
     * <p>
     * 為防止client利用反射調用私有改造函數,所以在創建第二個實例的時候拋出了異常
     * 
     * @author landon
     * @since 1.6.0_35
     * @version 1.0.0 2013-1-9
     * 
     
    */


    public class Singleton1
    {
        
    public static final Singleton1 instance = new Singleton1();

        
    // 私有改造函數
        private Singleton1()
        
    {
            
    if (instance != null)
            
    {
                
    throw new IllegalArgumentException("No exist the second instance");
            }

        }


        
    // 其他方法實現
        public void otherMethod()
        
    {
            
    // 
            System.out.println("call otherMethod");
        }


        @SuppressWarnings("rawtypes")
        
    public static void main(String args) throws Exception
        
    {
            Singleton1 singleton = Singleton1.instance;
            singleton.otherMethod();

            
    // 利用反射調用私有構造器
            Constructor[] arrayConstructor = singleton.getClass()
                    .getDeclaredConstructors();
            
    for (Constructor constructor : arrayConstructor)
            
    {
                
    // 調用setAccessible(true);
                constructor.setAccessible(true);

                
    // 實例化,這里一定會拋出異常
                constructor.newInstance();
            }

        }

    }


    package com.book.chap2.singleton;

    import java.io.Serializable;

    /**
    *
    *單例實現2
    *<p>公有的成員為靜態工廠方法
    *<p>序列化時,要實現readResolve方法,防止反序列化出新的實例
    *
    *@author landon
    *@since 1.6.0_35
    *@version 1.0.0 2013-1-9
    *
    */


    public class Singleton2 implements Serializable
    {
       
    //私有static Instance
        private static final Singleton2 INSTANCE = new Singleton2();
       
       
    //私有構造函數
        private Singleton2()
       
    {
        }

       
       
    //獲取單例方法
        public static Singleton2 getInstance()
       
    {
           
    return INSTANCE;
        }

       
       
    //其他方法
        public void otherMethod()
       
    {
           
    //
        }

       
       
    //必須提供該方法,以便重新指定反序列化得到的對象.
        private Object readResolve()
       
    {
           
    return INSTANCE;
        }

    }


    package com.book.chap2.singleton;

    import java.lang.reflect.Constructor;

    /**
    *
    *枚舉實現單例
    *<p>目前最好的方式,避免了反射的攻擊和序列化的問題
    *
    *<pre>
    *反射調用枚舉私有構造函數測試結果:
    *    Exception in thread "main" java.lang.IllegalArgumentException: Cannot reflectively create enum objects
        at java.lang.reflect.Constructor.newInstance(Unknown Source)
        at com.book.chap2.singleton.Singleton3.main(Singleton3.java:34)
    *</pre>
    *
    *@author landon
    *@since 1.6.0_35
    *@version 1.0.0 2013-1-9
    *
    */


    public enum Singleton3 {
        INSTANCE;
       
       
    public void otherMethod()
       
    {
        }

       
       
    public static void main(Stringargs) throws Exception
       
    {
           
    //測試,是否可以反射生成枚舉
           
    // 利用反射調用私有構造器
            Constructor[] arrayConstructor = Singleton3.INSTANCE.getClass().ge        tDeclaredConstructors();
    for (Constructor constructor : arrayConstructor)
           
    {
               
    // 調用setAccessible(true);
                constructor.setAccessible(true);

               
    // 實例化,這里一定會拋出異常
                constructor.newInstance();
            }

        }


    }

    posted on 2013-03-15 15:38 landon 閱讀(2518) 評論(2)  編輯  收藏 所屬分類: Program 、Book

    FeedBack:
    # re: Effective Java 2nd筆記3:用私有構造器或者枚舉類型強化Singleton屬性
    2013-03-16 10:49 | 背道而馳
    注:享有特權的client可以借助AccessibleObject.setAccessible方法,通過反射機制調用私有構造器。如果要抵御這種攻擊,需要修改構造器,讓其在創建第二個實例的時候拋出異常。

    請問樓主啊,如果判斷是第二次創建實例?  回復  更多評論
      
    # re: Effective Java 2nd筆記3:用私有構造器或者枚舉類型強化Singleton屬性
    2013-03-16 11:08 | 背道而馳
    剛才看了后面曉得了,謝謝樓主的分享??!  回復  更多評論
      
    主站蜘蛛池模板: 久久久久久99av无码免费网站| 亚洲暴爽av人人爽日日碰| 国产精品亚洲一区二区三区在线| 国产国产成年年人免费看片| 热99re久久免费视精品频软件| 美女视频黄的全免费视频网站| 4444www免费看| 黄色网址免费大全| 亚洲视频免费一区| 性短视频在线观看免费不卡流畅| 国产又大又粗又长免费视频| 日韩在线免费视频| 好男人看视频免费2019中文 | 亚洲av第一网站久章草| 久久无码av亚洲精品色午夜| 看全免费的一级毛片| 人妖系列免费网站观看| 国产成人精品免费视频大全| 久99久无码精品视频免费播放| 国产免费一级高清淫曰本片| 中文字幕无码免费久久| 最近中文字幕2019高清免费 | 婷婷亚洲综合五月天小说在线| 99亚洲精品卡2卡三卡4卡2卡| 又长又大又粗又硬3p免费视频| 最近免费中文字幕MV在线视频3| 99热在线免费播放| 免费不卡视频一卡二卡| 国产成人精品免费视频软件| 亚洲国产精品毛片av不卡在线| 亚洲精品无码国产| 国产成人亚洲合集青青草原精品 | 久久亚洲精品视频| 亚洲精品熟女国产| 亚洲国产精品成人综合色在线| a一级爱做片免费| 日本在线看片免费人成视频1000| 国产免费AV片在线播放唯爱网| 免费一级国产生活片| 日本亚洲欧洲免费天堂午夜看片女人员| 亚洲成在人天堂在线|