Java反射簡單使用--第一次細(xì)致閱讀底層代碼

1:所寫的東西都經(jīng)過驗(yàn)證,保證正確,環(huán)境jdk8,eclipse
2:在例子中,盡量以生產(chǎn)環(huán)境中實(shí)際代碼為例,那種固定值什么的沒什么意義

DynamicQuartzJob    Logger logger = LoggerFactory.getLogger(DynamicQuartzJob.  executeInternal(JobExecutionContext jobexecutioncontext) 
        JobDetailImpl jobDetail ==  JobExecutionException("can not find service info, because desription is empty"= name.split("\\."
        String beanName = serviceInfo[1
        String methodName = serviceInfo[2==
        JobDataMap dataMap ==== JSONObject.toBean(JSONObject.fromObject(dataMap.get("data"
 "%s %d"   .aa = .bb =   main(String[] args) 
        String str = "{\r\n" + "    \"aa\": \"zhangsan\",\r\n" + "    \"bb\": 1\r\n" + "}"
        Test test =  Test();        test = (Test) JSONObject.toBean(JSONObject.fromObject(str), Test.

5:拓展
(1):這張圖片是常用的反射方法

(2 java.lang.reflect.*    main(String[] args) 
        HelloKitty ht = =
        Class clazz1 = HelloKitty.
        Class clazz2 = Class.forName("HelloKitty"
        ClassLoader c == String.
        Object obj =
        Constructor[] con =+ " "
        Method[] mm =+ " "
        Method m = clazz2.getMethod("walk",=+ " "
        Method m1 = clazz2.getMethod("walk", "hahahhha"
        Constructor cc = clazz2.getConstructor(.,String.= cc.newInstance(12,"blue"
        Field ffs = clazz2.getDeclaredField("age"29=  String color = "pink" HelloKitty(.age = HelloKitty(.age =.color ="okokok" "hhhhhhhhhhhhh"  talk(+ "----------" +

6:如果只是應(yīng)用,網(wǎng)上文章一大堆,用就要知道一些具體的細(xì)節(jié),不然 emmmm.....(不引戰(zhàn),懂就好)

這里說一下核心方法 method.invoke

(1)這是invoke 的入口方法/**
     * Invokes the underlying method represented by this {@code Method}
     * object, on the specified object with the specified parameters.
     * Individual parameters are automatically unwrapped to match
     * primitive formal parameters, and both primitive and reference
     * parameters are subject to method invocation conversions as
     * necessary.
     *
     *If the underlying method is static, then the specified {@code obj}
     * argument is ignored. It may be null.
     *
     *If the number of formal parameters required by the underlying method is
     * 0, the supplied {@code args} array may be of length 0 or null.
     *
     *If the underlying method is an instance method, it is invoked
     * using dynamic method lookup as documented in The Java Language
     * Specification, Second Edition, section 15.12.4.4; in particular,
     * overriding based on the runtime type of the target object will occur.
     *
     *If the underlying method is static, the class that declared
     * the method is initialized if it has not already been initialized.
     *
     *If the method completes normally, the value it returns is
     * returned to the caller of invoke; if the value has a primitive
     * type, it is first appropriately wrapped in an object. However,
     * if the value has the type of an array of a primitive type, the
     * elements of the array are not wrapped in objects; in
     * other words, an array of primitive type is returned.  If the
     * underlying method return type is void, the invocation returns
     * null.
     *
     * @param obj  the object the underlying method is invoked from
     * @param args the arguments used for the method call
     * @return the result of dispatching the method represented by
     * this object on {@code obj} with parameters
     * {@code args}
     *
     * @exception IllegalAccessException    if this {@code Method} object
     *              is enforcing Java language access control and the underlying
     *              method is inaccessible.
     * @exception IllegalArgumentException  if the method is an
     *              instance method and the specified object argument
     *              is not an instance of the class or interface
     *              declaring the underlying method (or of a subclass
     *              or implementor thereof); if the number of actual
     *              and formal parameters differ; if an unwrapping
     *              conversion for primitive arguments fails; or if,
     *              after possible unwrapping, a parameter value
     *              cannot be converted to the corresponding formal
     *              parameter type by a method invocation conversion.
     * @exception InvocationTargetException if the underlying method
     *              throws an exception.
     * @exception NullPointerException      if the specified object is null
     *              and the method is an instance method.
     * @exception ExceptionInInitializerError if the initialization
     * provoked by this method fails.     */@CallerSensitive    public Object invoke(Object obj, Object... args)        throws IllegalAccessException, IllegalArgumentException,
           InvocationTargetException
    {        if (!override) {            if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
                Class caller = Reflection.getCallerClass();
                checkAccess(caller, clazz, obj, modifiers);
            }
        }
        MethodAccessor ma = methodAccessor;             // read volatile
        if (ma == null) {
            ma = acquireMethodAccessor();
        }        return ma.invoke(obj, args);
    }

(2)這段英文就不具體翻譯啦,大致意思就是使用這個方法的各種可能情況,可能出現(xiàn)的問題,特別提醒,如果練習(xí)英語但是不會FQ,看不到國外的文章可以看底層代碼的注釋,一樣可以練習(xí)英語
(3)開始正式解讀這個方法,首先說一下這注解@CallerSensitive

2->反射1->

(3):invoke方法可以分為倆部分,一部分是訪問控制檢查,第一個if;第二部分就是MethodAccessor。invoke()實(shí)現(xiàn)執(zhí)行方法

針對第一部分:簡單來說就是訪問權(quán)限檢查,判斷你是否可以訪問這個方法

具體來說就是: 檢查override,如果override為true,(Method的父類AccessibleObject中聲明的變量)跳過檢查;否則繼續(xù); 快速檢查,判斷該方法的修飾符modifiers是否為public,如果是跳過檢查;否則繼續(xù); 詳細(xì)檢查,通過方法的( protected / private / package )修飾符或方法的聲明類(例如子類可以訪問父類的protected方法)與調(diào)用者caller之間的關(guān)系,判斷caller是否有權(quán)限訪問該方法。這里推薦看一下java四種訪問權(quán)限,可能我們一般只用到private和public,但訪問權(quán)限控制很重要,在一些多人合作的項(xiàng)目中尤為重要

這里就涉及到一個有意思的 Field(他父類也是AccessibleObject),他的override是false,導(dǎo)致我們在獲取屬性是常用setAccessible(true),當(dāng)屬性為private修飾

針對第二部分MethodAccessor.invoke();也就是真正的調(diào)用方法

這里有一個注釋  // read volatile,這個很有意思是,volatile 是一個類型修飾符。volatile 的作用是作為指令關(guān)鍵字,確保本條指令不會因編譯器的優(yōu)化而省略。//這是methodAccessor,對應(yīng)的代碼private volatile MethodAccessor methodAccessor;
   
        MethodAccessor tmp =  (root != ) tmp = (tmp != =
            tmp = reflectionFactory.newMethodAccessor(
    =
         (root != //這個方法可能會導(dǎo)致類膨脹
//類膨脹:類的膨脹(Bloating)指的是類中成員過多,甚至出現(xiàn)無序增加的情況。過大的類,會使得復(fù)雜度急劇增加,維護(hù)會變得更為困難。所以需要控制類的增長。
//,這篇文章講解類膨脹= = =
注意這個方法acquireMethodAccessor,他有一個調(diào)用反射工廠的過程,ReflectionFactory利用MethodAccessor的字節(jié)碼生成類MethodAccessorGenerator直接創(chuàng)建一個代理類,通過間接調(diào)用原方法完成invoke()任務(wù);
這句話有幾個概念:字節(jié)碼,動態(tài)代理,反射最終都是調(diào)用原始類
這些遺留問題日后在解決把?。?!

7:總結(jié)一下我理解的反射和應(yīng)用場景

(1)反射的概念:可以理解成你去了一個小黑屋,里面可能有各種東西,都上了鎖,你通過反射就能獲取里面的東西,并且去除鎖,知道東西的真正面目

(2)反射應(yīng)用場景:簡單來說就是“動態(tài)帶有固定”,舉個例子,比如我上面的例子,方法是動態(tài)的,但是方法的參數(shù)是固定的;傳入的參數(shù)固定的,但是順序未必和方法一致的;

有話說:看完覺得有用的話可以點(diǎn)贊+評論,今后會分享更多關(guān)于java知識相關(guān)的文章!

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容