java反射與注解(二):Constructor類理解


Constructor類理解

這里Constructor旬迹,我們知道是構(gòu)造函數(shù)
為什么是數(shù)組形式的呢?
因?yàn)榭赡苡卸鄠€(gè)構(gòu)造
這個(gè)時(shí)候求类,我們寫一個(gè)DummyClass2奔垦, 這里有2個(gè)構(gòu)造
其他和前面一個(gè)Bean類似,有setter尸疆,getter椿猎,toString方法
這個(gè)時(shí)候,我們分別打印一下DummyClass和 DummyClass2 的 Constructor

具體打印工具方法

private static void printConstructor(Constructor<?>[] cons){
    for(int i=0; i<cons.length; i++){
        System.out.println(cons[i]);
    }
}

具體打印方法

private void getAndPrintConstructors(Class cls){
    Class<?> c1 = cls;
    Constructor<?>[] cons= c1.getConstructors();
    DUtils.printConstructor(cons);
}

具體簡單調(diào)用

DoConstructor doClass = new DoConstructor();
doClass.getAndPrintConstructors(DummyClass.class);
doClass.getAndPrintConstructors(DummyClass2.class);

具體我們可以看見結(jié)果

public com.aohuan.dodo.javacode.reflect.utils.DummyClass()
- - -
public com.aohuan.dodo.javacode.reflect.utils.DummyClass2(java.lang.String)
public com.aohuan.dodo.javacode.reflect.utils.DummyClass2(java.lang.String,int)

也就是寿弱,對象可以得到這個(gè)Class中犯眠,所有的構(gòu)造方法
對應(yīng)的構(gòu)造方法雌团,會(huì)通過數(shù)組返回
如果我們需要知道一個(gè)類中篇裁,有哪些構(gòu)造方法贞言,就可以這樣去做了
當(dāng)然拂苹,得到構(gòu)造,也就是為了創(chuàng)建實(shí)例挡鞍,
我們下面再一起回顧newInstance()方法


newInstance()方法法褥,深入

我們先看一下源碼

public T newInstance()
    throws InstantiationException, IllegalAccessException
{
    if (System.getSecurityManager() != null) {
        checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), false);
    }

    // NOTE: the following code may not be strictly correct under
    // the current Java memory model.

    // Constructor lookup
    if (cachedConstructor == null) {
        if (this == Class.class) {
            throw new IllegalAccessException(
                "Can not call newInstance() on the Class for java.lang.Class"
            );
        }
        try {
            Class<?>[] empty = {};
            final Constructor<T> c = getConstructor0(empty, Member.DECLARED);
            // Disable accessibility checks on the constructor
            // since we have to do the security check here anyway
            // (the stack depth is wrong for the Constructor's
            // security check to work)
            java.security.AccessController.doPrivileged(
                new java.security.PrivilegedAction<Void>() {
                    public Void run() {
                            c.setAccessible(true);
                            return null;
                        }
                    });
            cachedConstructor = c;
        } catch (NoSuchMethodException e) {
            throw new InstantiationException(getName());
        }
    }
    Constructor<T> tmpConstructor = cachedConstructor;
    // Security check (same as in java.lang.reflect.Constructor)
    int modifiers = tmpConstructor.getModifiers();
    if (!Reflection.quickCheckMemberAccess(this, modifiers)) {
        Class<?> caller = Reflection.getCallerClass();
        if (newInstanceCallerCache != caller) {
            Reflection.ensureMemberAccess(caller, this, null, modifiers);
            newInstanceCallerCache = caller;
        }
    }
    // Run constructor
    try {
        return tmpConstructor.newInstance((Object[])null);
    } catch (InvocationTargetException e) {
        Unsafe.getUnsafe().throwException(e.getTargetException());
        // Not reached
        return null;
    }
}

前面的判斷權(quán)限卖氨,判斷調(diào)用不在對應(yīng)的Class類型中
也就是
throw new IllegalAccessException(
"Can not call newInstance() on the Class for java.lang.Class");
異常等問題的處理艇挨,我們略

下面通過getConstructor0(empty, Member.DECLARED);
獲得一個(gè) Constructor<T>残炮,在執(zhí)行方法(執(zhí)行的方法,我們后面幾節(jié)會(huì)提到)
這里對應(yīng)的getConstructor0方法

private Constructor<T> getConstructor0(Class<?>[] parameterTypes,
                                    int which) throws NoSuchMethodException
{
    Constructor<T>[] constructors = privateGetDeclaredConstructors((which == Member.PUBLIC));
    for (Constructor<T> constructor : constructors) {
        if (arrayContentsEq(parameterTypes,
                            constructor.getParameterTypes())) {
            return getReflectionFactory().copyConstructor(constructor);
        }
    }
    throw new NoSuchMethodException(getName() + ".<init>" + argumentTypesToString(parameterTypes));
}

這里大致
Constructor<T>[] constructors = privateGetDeclaredConstructors((which == Member.PUBLIC));
先獲得Constructor數(shù)組(這里which傳入的是Member.DECLARED雷袋,所以為false)
這樣就會(huì)拿到所有的構(gòu)造吉殃,包括非public的
再會(huì)
arrayContentsEq(parameterTypes,constructor.getParameterTypes())
for each循環(huán)去判斷

private static boolean arrayContentsEq(Object[] a1, Object[] a2) {
    if (a1 == null) {
        return a2 == null || a2.length == 0;
    }

    if (a2 == null) {
        return a1.length == 0;
    }

    if (a1.length != a2.length) {
        return false;
    }

    for (int i = 0; i < a1.length; i++) {
        if (a1[i] != a2[i]) {
            return false;
        }
    }

    return true;
}

這里大體的判斷邏輯
我們外面對應(yīng)的Class<?>[] empty = {};
所以辞居,走第一個(gè) return a2 == null || a2.length == 0;
我們沒有對應(yīng)的構(gòu)造(默認(rèn)的構(gòu)造楷怒,應(yīng)該是后面的邏輯添加進(jìn)去的,不會(huì)影響這里的邏輯)
這樣瓦灶,我們可以知道鸠删,當(dāng)我們不寫構(gòu)造的時(shí)候,會(huì)觸發(fā)創(chuàng)建對象
并且返回 tmpConstructor.newInstance((Object[])null);*
也就是默認(rèn)調(diào)用參數(shù)為null的構(gòu)造

換句話說贼陶,
Class的newInstance刃泡,
其實(shí)是調(diào)用的Constructor.newInstance((Object[])null);

修改構(gòu)造巧娱,測試
這個(gè)時(shí)候,我們調(diào)用 DummyClass2 的 newInstance() 試試
(因?yàn)?DummyClass2 有2個(gè)構(gòu)造方法烘贴,而對應(yīng)的Class的newInstance如果參數(shù)判斷通過的前提下禁添,傳入的也是空的構(gòu)造,這樣肯定會(huì)報(bào)錯(cuò))

我們運(yùn)行測試

/**
 *  我們調(diào)用Class的getConstructor的 newInstance((Object[])null);
 *  具體的結(jié)果桨踪,我們可以看見老翘,和前面DoClass類的newInstance方法結(jié)果一樣
 * @throws IllegalAccessException
 * @throws InstantiationException
 * @throws NoSuchMethodException
 * @throws InvocationTargetException
 */
private void doConstructorNewInstance1() throws IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
    Class<?> c1 = DummyClass.class;
    DUtils.println(c1.getConstructor().newInstance((Object[])null).toString());
}

我們調(diào)用Class的getConstructor的 newInstance((Object[])null);
具體的結(jié)果,
DummyClass{age=0, name='null'}
我們可以看見锻离,和前面DoClass類的newInstance方法結(jié)果一樣

再看看調(diào)用DummyClass2的構(gòu)造方法

/**
 *  我們調(diào)用Class的getConstructor的 newInstance("dodo");
 *      會(huì)報(bào)錯(cuò)铺峭,因?yàn)樵创a中,只有沒有寫構(gòu)造的時(shí)候汽纠,才會(huì)按上面的流程走
 * @throws IllegalAccessException
 * @throws InstantiationException
 * @throws NoSuchMethodException
 * @throws InvocationTargetException
 */
private void doConstructorNewInstance2E() throws IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
    Class<?> c2 = DummyClass2.class;
    DUtils.println(c2.getConstructor().newInstance("dodo").toString());
}

對應(yīng)的結(jié)果卫键,是

Exception in thread "main" java.lang.NoSuchMethodException: com.aohuan.dodo.javacode.reflect.utils.DummyClass2.<init>()
    at java.lang.Class.getConstructor0(Class.java:2971)
    at java.lang.Class.getConstructor(Class.java:1812)
    at com.aohuan.dodo.javacode.reflect.sample1.DoConstructor.doConstructorNewInstance2E(DoConstructor.java:61)
    at com.aohuan.dodo.javacode.reflect.sample1.DoConstructor.main(DoConstructor.java:23)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:483)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:140)

可以發(fā)現(xiàn),對應(yīng)的邏輯是正確的
那如果構(gòu)造中虱朵,有多個(gè)參數(shù)怎么辦莉炉?
我們試試newInstance方法后面,帶下參數(shù)碴犬?
發(fā)現(xiàn)呢袱,Class就只有newInstance()這一個(gè)創(chuàng)建對象的方法
....

那我們回想下前面提到的Constructor類


Constructor 類 newInstance()

那我們嘗試一下對應(yīng)的 Constructor類 調(diào)用2個(gè)構(gòu)造的方法試試

/**
 *  DummyClass2 有2個(gè)自己的帶參數(shù)的構(gòu)造
 *  如果通過getConstructors得到構(gòu)造的數(shù)組,在調(diào)用對應(yīng)的構(gòu)造翅敌,傳入?yún)?shù)即可
 * @throws IllegalAccessException
 * @throws InstantiationException
 */
private void doConstructorNewInstance2R1() throws IllegalAccessException, InstantiationException, InvocationTargetException {
    Class<DummyClass2> c2 = DummyClass2.class;
    DUtils.println(c2.getConstructors()[1].newInstance("dodo", 23).toString());
}

這個(gè)時(shí)候羞福,我們可以打印對應(yīng)的bean2
結(jié)果為:
DummyClass{age=23, name='dodo'}

這個(gè)時(shí)候,我們知道我們有2個(gè)構(gòu)造
同理蚯涮,我們可以
c2.getConstructors()[0].newInstance("dodo").toString();
拿到index為0的Constructor構(gòu)造類治专,
打印也可以得到結(jié)果
DummyClass{age=0, name='dodo'}
這里age是一般數(shù)據(jù)類型,不賦值遭顶,結(jié)果為0

具體Constructor 類的 public T newInstance(Object ... initargs)
我們就不繼續(xù)跟了
因?yàn)橐蕾嚨?ConstructorAccessor 類张峰,和今天討論的主題 有點(diǎn)遠(yuǎn)了
再加上 沒有源碼
就不繼續(xù)扯了


其他簡單說明

Constructor:

  • getConstructors() : 獲取 public的 Constructor[](public)
  • getDeclaredConstructors() : 獲取 所有的 Constructor[]
  • getConstructor(parameterTypes) : 根據(jù) 參數(shù)類型(可變參數(shù)), 獲取具體 Constructor(public)
  • getDeclaredConstructor(parameterTypes):根據(jù) 參數(shù)類型(可變參數(shù))棒旗, 獲取具體 Constructor

這里

  • getConstructors()方法
    • 是獲取 public的構(gòu)造函數(shù) 數(shù)組
  • getDeclaredConstructors()方法
    • 是獲取所有的構(gòu)造函數(shù) 數(shù)組
  • getConstructor(parameterTypes) 方法
    • 是根據(jù) 參數(shù)類型(可以有多個(gè)Class<?>的可變參數(shù))喘批,
    • 獲取具體public的 Constructor
  • getDeclaredConstructor(parameterTypes) 方法,
    • 是根據(jù) 參數(shù)類型(可以有多個(gè)Class<?>的可變參數(shù))铣揉,
    • 獲取具體的 Constructor

簡單總結(jié)

這里大致了解下
Class的簡單使用 和 大體作用

其他的內(nèi)容饶深,后續(xù)一起學(xué)習(xí)具體代碼,可以見
https://github.com/2954722256/use_little_demo
對應(yīng) javacode 的 Module逛拱,對應(yīng)的reflect包

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末敌厘,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子朽合,更是在濱河造成了極大的恐慌俱两,老刑警劉巖饱狂,帶你破解...
    沈念sama閱讀 211,123評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異宪彩,居然都是意外死亡休讳,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,031評論 2 384
  • 文/潘曉璐 我一進(jìn)店門尿孔,熙熙樓的掌柜王于貴愁眉苦臉地迎上來衍腥,“玉大人,你說我怎么就攤上這事纳猫∑畔蹋” “怎么了?”我有些...
    開封第一講書人閱讀 156,723評論 0 345
  • 文/不壞的土叔 我叫張陵芜辕,是天一觀的道長尚骄。 經(jīng)常有香客問我,道長侵续,這世上最難降的妖魔是什么倔丈? 我笑而不...
    開封第一講書人閱讀 56,357評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮状蜗,結(jié)果婚禮上需五,老公的妹妹穿的比我還像新娘。我一直安慰自己轧坎,他們只是感情好宏邮,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,412評論 5 384
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著缸血,像睡著了一般蜜氨。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上捎泻,一...
    開封第一講書人閱讀 49,760評論 1 289
  • 那天飒炎,我揣著相機(jī)與錄音,去河邊找鬼笆豁。 笑死郎汪,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的闯狱。 我是一名探鬼主播煞赢,決...
    沈念sama閱讀 38,904評論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼扩氢!你這毒婦竟也來了耕驰?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,672評論 0 266
  • 序言:老撾萬榮一對情侶失蹤录豺,失蹤者是張志新(化名)和其女友劉穎朦肘,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體双饥,經(jīng)...
    沈念sama閱讀 44,118評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡媒抠,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,456評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了咏花。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片趴生。...
    茶點(diǎn)故事閱讀 38,599評論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖昏翰,靈堂內(nèi)的尸體忽然破棺而出苍匆,到底是詐尸還是另有隱情,我是刑警寧澤棚菊,帶...
    沈念sama閱讀 34,264評論 4 328
  • 正文 年R本政府宣布浸踩,位于F島的核電站,受9級特大地震影響统求,放射性物質(zhì)發(fā)生泄漏检碗。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,857評論 3 312
  • 文/蒙蒙 一码邻、第九天 我趴在偏房一處隱蔽的房頂上張望折剃。 院中可真熱鬧,春花似錦像屋、人聲如沸怕犁。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,731評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽因苹。三九已至,卻和暖如春篇恒,著一層夾襖步出監(jiān)牢的瞬間扶檐,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,956評論 1 264
  • 我被黑心中介騙來泰國打工胁艰, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留款筑,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,286評論 2 360
  • 正文 我出身青樓腾么,卻偏偏與公主長得像奈梳,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子解虱,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,465評論 2 348

推薦閱讀更多精彩內(nèi)容

  • 一攘须、概述 Java反射機(jī)制定義 Java反射機(jī)制是在運(yùn)行狀態(tài)中,對于任意一個(gè)類殴泰,都能夠知道這個(gè)類中的所有屬性和方法...
    CoderZS閱讀 1,631評論 0 26
  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語法于宙,類相關(guān)的語法浮驳,內(nèi)部類的語法,繼承相關(guān)的語法捞魁,異常的語法至会,線程的語...
    子非魚_t_閱讀 31,598評論 18 399
  • 前言,本來只是想研究一下注解的谱俭,不過發(fā)現(xiàn)奉件,要懂注解先得懂反射,別問我為什么昆著,你可以自己試試 JAVA反射 主要是指...
    justCode_閱讀 1,220評論 2 9
  • Class類簡介 Cass類位于jdk的java.lang包下 雖然不在反射包下面县貌,但是類中import了很多反射...
    dodo_lihao閱讀 1,258評論 0 9
  • 早安,山鷹凑懂! 2:00醒來煤痕,至此天亮,翻以前的Q 碰到了蘇音征候,被狠狠罵了一頓 "你不做茶杭攻,會(huì)死啊疤坝?” 頓時(shí)語塞兆解。 ...
    一轉(zhuǎn)一回閱讀 313評論 0 0