你必須掌的握反射用法

你必須掌的握反射用法

什么是反射

反射(Reflection)是Java 程序開(kāi)發(fā)語(yǔ)言的特征之一惑芭,它允許運(yùn)行中的 Java 程序獲取自身的信息立莉,并且可以操作類或?qū)ο蟮膬?nèi)部屬性悦施。
Oracle官方對(duì)反射的解釋是

Reflection enables Java code to discover information about the fields, methods and constructors of loaded classes, and to use reflected fields, methods, and constructors to operate on their underlying counterparts, within security restrictions.
The API accommodates applications that need access to either the public members of a target object (based on its runtime class) or the members declared by a given class. It also allows programs to suppress default reflective access control.

簡(jiǎn)而言之,通過(guò)反射尺迂,我們可以在運(yùn)行時(shí)獲得程序或程序集中每一個(gè)類型的成員和成員的信息掠拳。
程序中一般的對(duì)象的類型都是在編譯期就確定下來(lái)的,而Java反射機(jī)制可以動(dòng)態(tài)地創(chuàng)建對(duì)象并調(diào)用其屬性筐赔,這樣的對(duì)象的類型在編譯期是未知的铣猩。所以我們可以通過(guò)反射機(jī)制直接創(chuàng)建對(duì)象,即使這個(gè)對(duì)象的類型在編譯期是未知的茴丰。
?反射的核心是JVM在運(yùn)行時(shí)才動(dòng)態(tài)加載類或調(diào)用方法/訪問(wèn)屬性达皿,它不需要事先(寫代碼的時(shí)候或編譯期)知道運(yùn)行對(duì)象是誰(shuí)。

Java反射框架主要提供以下功能:

  • 判斷任意對(duì)象所屬的類贿肩;
  • 獲取一個(gè)類的任意對(duì)象(獲得Class對(duì)象)峦椰;
  • 獲取一個(gè)類所具有的任意成員變量和方法;
  • 構(gòu)造任意一個(gè)對(duì)象以及調(diào)用一個(gè)對(duì)象

這里說(shuō)的獲取特質(zhì)運(yùn)行時(shí)汰规,既編譯之后的行為汤功。通俗的講就是我們可以獲取Android 系統(tǒng)所有內(nèi)部類,private方法 變量控轿,@hide 的方法和變量 @internal 的方法和變量冤竹。。茬射。

Internal和hidden API的區(qū)別:
Hidden API之所以被隱藏鹦蠕,是想阻止開(kāi)發(fā)者使用SDK中那些未完成或不穩(wěn)定的部分(接口或架構(gòu))。
舉個(gè)例子在抛,Bluetooth API在API 5(Android 2.0)上才開(kāi)放钟病;在API 3 和4上都是用@hide屬性隱藏了。當(dāng)這些API被驗(yàn)證和清理后刚梭,Google的開(kāi)發(fā)者會(huì)移除@hide屬性肠阱,并讓其在API 5官方化。很多地方在API 4 和5之間發(fā)生了變化朴读。如果你的程序依賴某些隱藏的API屹徘,當(dāng)其部署到新的平臺(tái)上時(shí),就有可能陷入困境衅金。
對(duì)于internal API來(lái)說(shuō)噪伊,從來(lái)都沒(méi)有計(jì)劃將其開(kāi)放出來(lái)。它就是Android的“內(nèi)部廚房”氮唯,對(duì)開(kāi)發(fā)者來(lái)說(shuō)鉴吹,應(yīng)該將其視作黑盒。凡事都會(huì)有變化的惩琉。如果你依賴某些internal API豆励,也有可能在新的Android release上,這些internal API發(fā)生變化瞒渠,從而令你失望良蒸。

總結(jié)一下區(qū)別:
Hidden API = 進(jìn)行中的工作;
Internal API = 黑盒在孝;

反射的基本運(yùn)用

1. 獲得Class對(duì)象

方法有三種
(1)使用Class類的forName靜態(tài)方法:

方法:
public static Class<?> forName(String className)

java 調(diào)用:
 Class.forName("XXX.XXX.XXX");

(2)直接獲取某一個(gè)對(duì)象的class诚啃,比如:

Class<?> klass = int.class;
Class<?> classInt = Integer.TYPE;

(3)調(diào)用某個(gè)對(duì)象的getClass()方法,比如:

StringBuilder str = new StringBuilder("123");
Class<?> klass = str.getClass();

2. 判斷是否為某個(gè)類的實(shí)例

代碼調(diào)用:
String label  = " XXXXX ";
if (label instanceof Objects) {
//do something
}
反射native方法如下:   
public native boolean isInstance(Object obj);

3. 創(chuàng)建實(shí)例

通過(guò)反射來(lái)生成對(duì)象主要有兩種方式。
(1)使用Class對(duì)象的newInstance()方法來(lái)創(chuàng)建Class對(duì)象對(duì)應(yīng)類的實(shí)例私沮。

Class<?> c = String.class;
Object str = c.newInstance();

(2)先通過(guò)Class對(duì)象獲取指定的Constructor對(duì)象始赎,再調(diào)用Constructor對(duì)象的newInstance()方法來(lái)創(chuàng)建實(shí)例。這種方法可以用指定的構(gòu)造器構(gòu)造類的實(shí)例仔燕。

//獲取String所對(duì)應(yīng)的Class對(duì)象
Class<?> c = String.class;
//獲取String類帶一個(gè)String參數(shù)的構(gòu)造器
Constructor constructor = c.getConstructor(String.class);
//根據(jù)構(gòu)造器創(chuàng)建實(shí)例
Object obj = constructor.newInstance("23333");
System.out.println(obj);

4. 獲取方法

獲取某個(gè)Class對(duì)象的方法集合造垛,主要有以下幾個(gè)方法:
getDeclaredMethods()方法返回類或接口聲明的所有方法,包括公共晰搀、保護(hù)五辽、默認(rèn)(包)訪問(wèn)和私有方法,但不包括繼承的方法外恕。 (除了父類的)

public Method[] getDeclaredMethods() throws SecurityException

getMethods()方法返回某個(gè)類的所有公用(public)方法杆逗,包括其繼承類的公用方法乡翅。(只能拿到公共的, 包括父類的)

public Method[] getMethods() throws SecurityException

getMethod方法返回一個(gè)特定的方法,其中第一個(gè)參數(shù)為方法名稱罪郊,后面的參數(shù)為方法的參數(shù)對(duì)應(yīng)Class的對(duì)象(無(wú)限制)

public Method getMethod(String name, Class<?>... parameterTypes)

5. 獲取構(gòu)造器信息

獲取類構(gòu)造器的用法與上述獲取方法的用法類似蠕蚜。主要是通過(guò)Class類的getConstructor方法得到Constructor類的一個(gè)實(shí)例,而Constructor類有一個(gè)newInstance方法可以創(chuàng)建一個(gè)對(duì)象實(shí)例:

public T newInstance(Object ... initargs)

此方法可以根據(jù)傳入的參數(shù)來(lái)調(diào)用對(duì)應(yīng)的Constructor創(chuàng)建對(duì)象實(shí)例~

6. 獲取類的成員變量(字段)信息

主要以下這幾個(gè)方法:
getFiled: 訪問(wèn)公有的成員變量
getDeclaredField:所有已聲明的成員變量悔橄。但不能得到其父類的成員變量
getFileds和getDeclaredFields用法同上(參照Method)

7. 調(diào)用方法

當(dāng)我們從類中獲取了一個(gè)方法后靶累,我們就可以用invoke()方法來(lái)調(diào)用這個(gè)方法。invoke方法的原型為:

public Object invoke(Object obj, Object... args)
        throws IllegalAccessException, IllegalArgumentException,
           InvocationTargetException

8. 利用反射調(diào)用 android @hide 方法的一個(gè)例子

package android.text;
public class StaticLayout extends Layout {}
里面有一個(gè)構(gòu)造方法是@hide 怎么調(diào)用癣疟,答案在后面一篇文章給出
注意 參數(shù)int l類型的應(yīng)該使用 int.class ( Integer.TYPE;)

  /**
     * @hide
     */
    public StaticLayout(CharSequence source, int bufstart, int bufend,
                        TextPaint paint, int outerwidth,
                        Alignment align, TextDirectionHeuristic textDir,
                        float spacingmult, float spacingadd,
                        boolean includepad,
                        TextUtils.TruncateAt ellipsize, int ellipsizedWidth, int maxLines) {
        super((ellipsize == null)
                ? source
                : (source instanceof Spanned)
                    ? new SpannedEllipsizer(source)
                    : new Ellipsizer(source),
              paint, outerwidth, align, textDir, spacingmult, spacingadd);

        Builder b = Builder.obtain(source, bufstart, bufend, paint, outerwidth)
            .setAlignment(align)
            .setTextDirection(textDir)
            .setLineSpacing(spacingadd, spacingmult)
            .setIncludePad(includepad)
            .setEllipsizedWidth(ellipsizedWidth)
            .setEllipsize(ellipsize)
            .setMaxLines(maxLines);
        /*
         * This is annoying, but we can't refer to the layout until
         * superclass construction is finished, and the superclass
         * constructor wants the reference to the display text.
         *
         * This will break if the superclass constructor ever actually
         * cares about the content instead of just holding the reference.
         */
        if (ellipsize != null) {
            Ellipsizer e = (Ellipsizer) getText();

            e.mLayout = this;
            e.mWidth = ellipsizedWidth;
            e.mMethod = ellipsize;
            mEllipsizedWidth = ellipsizedWidth;

            mColumns = COLUMNS_ELLIPSIZE;
        } else {
            mColumns = COLUMNS_NORMAL;
            mEllipsizedWidth = outerwidth;
        }

        mLineDirections = ArrayUtils.newUnpaddedArray(Directions.class, 2 * mColumns);
        mLines = new int[mLineDirections.length];
        mMaximumVisibleLineCount = maxLines;

        generate(b, b.mIncludePad, b.mIncludePad);

        Builder.recycle(b);
    }
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末挣柬,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子睛挚,更是在濱河造成了極大的恐慌邪蛔,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,080評(píng)論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件扎狱,死亡現(xiàn)場(chǎng)離奇詭異店溢,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)委乌,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,422評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門床牧,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人遭贸,你說(shuō)我怎么就攤上這事戈咳。” “怎么了壕吹?”我有些...
    開(kāi)封第一講書人閱讀 157,630評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵著蛙,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我耳贬,道長(zhǎng)踏堡,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書人閱讀 56,554評(píng)論 1 284
  • 正文 為了忘掉前任咒劲,我火速辦了婚禮顷蟆,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘腐魂。我一直安慰自己帐偎,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,662評(píng)論 6 386
  • 文/花漫 我一把揭開(kāi)白布蛔屹。 她就那樣靜靜地躺著削樊,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上漫贞,一...
    開(kāi)封第一講書人閱讀 49,856評(píng)論 1 290
  • 那天甸箱,我揣著相機(jī)與錄音,去河邊找鬼迅脐。 笑死摇肌,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的仪际。 我是一名探鬼主播,決...
    沈念sama閱讀 39,014評(píng)論 3 408
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼昵骤,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼树碱!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起变秦,我...
    開(kāi)封第一講書人閱讀 37,752評(píng)論 0 268
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤成榜,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后蹦玫,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體赎婚,經(jīng)...
    沈念sama閱讀 44,212評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,541評(píng)論 2 327
  • 正文 我和宋清朗相戀三年樱溉,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了挣输。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,687評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡福贞,死狀恐怖撩嚼,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情挖帘,我是刑警寧澤完丽,帶...
    沈念sama閱讀 34,347評(píng)論 4 331
  • 正文 年R本政府宣布,位于F島的核電站拇舀,受9級(jí)特大地震影響逻族,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜骄崩,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,973評(píng)論 3 315
  • 文/蒙蒙 一聘鳞、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧要拂,春花似錦搁痛、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 30,777評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至枪芒,卻和暖如春彻况,著一層夾襖步出監(jiān)牢的瞬間谁尸,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 32,006評(píng)論 1 266
  • 我被黑心中介騙來(lái)泰國(guó)打工纽甘, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留良蛮,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,406評(píng)論 2 360
  • 正文 我出身青樓悍赢,卻偏偏與公主長(zhǎng)得像决瞳,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子左权,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,576評(píng)論 2 349

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