80%的Java程序員不知道反射強(qiáng)行調(diào)用私有構(gòu)造器這事兒
在我之前的一篇文章里曾提到一個(gè)觀點(diǎn):“可能會(huì)有人使用反射強(qiáng)行調(diào)用我們的私有構(gòu)造器”,很多童鞋不明白Java反射機(jī)制怎么做到調(diào)用私有構(gòu)造器,今天我們來(lái)做一個(gè)實(shí)驗(yàn)。
實(shí)驗(yàn)代碼
- 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());
- }
- }
實(shí)驗(yàn)結(jié)果
注釋1處的代碼cons.setAccessible(true),執(zhí)行main函數(shù),出現(xiàn)異常Exception in thread "main"
- java.lang.IllegalAccessException: Class ReflectTest can not access a member of class TestOne with modifiers "private"
開(kāi)啟1處的代碼cons.setAccessible(true),執(zhí)行main函數(shù),出現(xiàn)如下正常的初始化信息:
- init TestOne==12677476
- init TestOne==33263331
這說(shuō)明私有構(gòu)造函數(shù)被多次成功調(diào)用,注意是私有構(gòu)造函數(shù)哦。
實(shí)驗(yàn)總結(jié)
出現(xiàn)完全不同的兩種測(cè)試結(jié)果的原因是什么?我們來(lái)剖析一下cons.setAccessible(true)函數(shù),為什么設(shè)置為true時(shí),可以通過(guò)反射調(diào)用私有構(gòu)造器呢?我們定位到cons.setAccessible(true)源代碼,可以看到下面的英文說(shuō)明,右側(cè)已經(jīng)幫助大家翻譯了一下。
也就是說(shuō),Java反射機(jī)制非常強(qiáng)大,可以根據(jù)需要繞過(guò)Java語(yǔ)言的訪問(wèn)檢查。
原文是這樣說(shuō)的:
Set the accessible flag for this object to the indicated boolean value. A value of true indicates that the reflected object should suppress Java language access checking when it is used. A value of false indicates that the reflected object should enforce Java language access checks.
翻譯過(guò)來(lái)是這樣的:
- 將此對(duì)象的<tt>可訪問(wèn)</ tt>標(biāo)志設(shè)置為指示的布爾值。 值<tt> true </ tt>表示反射對(duì)象應(yīng)該在使用時(shí)抑制Java語(yǔ)言訪問(wèn)檢查。 值<tt> false </ tt>表示反射對(duì)象應(yīng)強(qiáng)制實(shí)施Java語(yǔ)言訪問(wèn)檢查。
【本文為51CTO專(zhuān)欄作者“朱國(guó)立”的原創(chuàng)稿件,轉(zhuǎn)載請(qǐng)通過(guò)作者微信公眾號(hào)“開(kāi)發(fā)者圓桌”獲取聯(lián)系和授權(quán)】