利用反射機制破壞單例模式

簡介

利用反射機制破壞了單例模式,這裏以懶漢單例模式爲例子進行操做。
以前利用反射也是改變了類中的private變量。
類中的private變量真的private麼?java

正常的單例模式的實現

這裏採用了懶漢的單例模式,順帶說一句我本身對懶漢餓漢的理解:
懶漢就是在類加載的時候並不建立對象的實例,在你用到的時候纔去建立一個實例。
餓漢就是無論你用不用到,這個類加載的時候就建立了一個實例。用到的時候就返回那個已經建立好的實例。
根本的區別在於建立實例的時機不一樣。segmentfault

單例模式的類:測試

public class SingleTest {
    private static SingleTest singleTest;
    private SingleTest(){}
    public static SingleTest getSingleTest()
    {
        if(singleTest==null)
        {
            singleTest = new SingleTest();
        }
        return singleTest;
    }
}

測試類:code

import java.lang.reflect.Field;

public class Test 
{
    
    public static void main(String args[])
    {    
        SingleTest s1 = SingleTest.getSingleTest();
        SingleTest s2 = SingleTest.getSingleTest();
        System.out.println("s1 hashCode: "+s1.hashCode());
        System.out.println("s2 hashCode: "+s2.hashCode());
    }
}

這個類中我打印了s1和s2的hashCode用來驗證是否是同一個對象。
輸出以下:對象

s1 hashCode: 2943240
s2 hashCode: 2943240

能夠看到s1和s2實際上是同一個實例。get

利用反射機制破壞單例模式

單例模式的類仍然不變。hash

測試類以下:io

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;

public class Test 
{
    
    public static void main(String args[])
    {    
        SingleTest s1 = SingleTest.getSingleTest();
        SingleTest s2 = SingleTest.getSingleTest();
        SingleTest s3 = null;
        System.out.println("s1 hashCode: "+s1.hashCode());
        System.out.println("s2 hashCode: "+s2.hashCode());
        
        Class singleClass = s1.getClass();
        try {
            Constructor constructor = singleClass.getDeclaredConstructor();
            constructor.setAccessible(true);
            s3 = (SingleTest) constructor.newInstance();
        } catch (Exception e) {
            e.printStackTrace();
        }
        
        System.out.println("s3 hashCode: "+s3.hashCode());
    }
}

輸出結果以下:class

s1 hashCode: 18262862
s2 hashCode: 18262862
s3 hashCode: 28420709

能夠看到s3和s1s2已經不是同一個實例了。import

就這樣,成功的破壞了單例模式。

仍是同樣,但願聽到你們對java封裝和反射等的理解。

相信能從你們的評論中學會不少。

相關文章
相關標籤/搜索