80%的Java程序員不知道反射強行調用私有構造器這事兒

文章轉載自「開發者圓桌」一個10年老猿原創文章傳播開發經驗,尤其適合初學者或剛入職場前幾年程序猿的微信公衆號。

wKioL1i5Ck7AkeuMAAChGHetiEM164.jpg



之前推送了一篇叫做你真的會寫單例模式嗎?」的文章,裏面提到一個觀點:“可能會有人使用反射強行調用我們的私有構造器”,看到在我們的開發者圓桌QQ交流羣162566098中,很多童鞋不明白Java反射機制怎麼做到調用私有構造器,今天我們來做一個實驗。


實驗代碼


import java.lang.reflect.*;

public class ReflectTest {

 public static void main(String[] args) throws Exception { 

//get Constructor

Class clazz = Class.forName("TestOne");

Constructor cons = clazz.getDeclaredConstructor(null); 

//set accessible to access private constructor  

cons.setAccessible(true); //1 

cons.newInstance(null); 

cons.newInstance(null); 

 }

}

class TestOne {

    private TestOne() {  

        System.out.println("init TestOne=="+this.hashCode());  

    }  

}


實驗結果


註釋1處的代碼cons.setAccessible(true),執行main函數,出現異常Exception in thread "main" java.lang.IllegalAccessException: Class ReflectTest can not access a member of class TestOne with modifiers "private"


開啓1處的代碼cons.setAccessible(true),執行main函數,出現如下正常的初始化信息:

init TestOne==12677476

init TestOne==33263331

這說明私有構造函數被多次成功調用,注意是私有構造函數哦。


實驗總結


出現完全不同的兩種測試結果的原因是什麼?我們來剖析一下cons.setAccessible(true)函數,爲什麼設置爲true時,可以通過反射調用私有構造器呢?我們定位到cons.setAccessible(true)源代碼,可以看到下面的英文說明,右側已經幫助大家翻譯了一下。

wKioL1kQQc6DNYfWAACKgkVjrEk185.jpg


也就是說,Java反射機制非常強大,可以根據需要繞過Java語言的訪問檢查。


原文是這樣說的:

Set the <tt>accessible</tt> flag for this object to the indicated boolean value.  A value of <tt>true</tt> indicates that the reflected object should suppress Java language access checking when it is used.  A value of <tt>false</tt> indicates that the reflected object should enforce Java language access checks.


翻譯過來是這樣的:

將此對象的<tt>可訪問</ tt>標誌設置爲指示的布爾值。 值<tt> true </ tt>表示反射對象應該在使用時抑制Java語言訪問檢查。 值<tt> false </ tt>表示反射對象應強制實施Java語言訪問檢查。



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章