Java反射简单使用--第一次细致阅读底层代码
  TEZNKK3IfmPf 2023年11月15日 59 0
1:所写的东西都经过验证,保证正确,环境jdk8,eclipse
2:在例子中,尽量以生产环境中实际代码为例,那种固定值什么的没什么意义
12312123434
  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):这张图片是常用的反射方法

Java反射简单使用--第一次细致阅读底层代码


(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:如果只是应用,网上文章一大堆,用就要知道一些具体的细节,不然 emmmm.....(不引战,懂就好)

这里说一下核心方法 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)这段英文就不具体翻译啦,大致意思就是使用这个方法的各种可能情况,可能出现的问题,特别提醒,如果练习英语但是不会FQ,看不到国外的文章可以看底层代码的注释,一样可以练习英语
(3)开始正式解读这个方法,首先说一下这注解@CallerSensitive
2->反射1->

(3):invoke方法可以分为俩部分,一部分是访问控制检查,第一个if;第二部分就是MethodAccessor。invoke()实现执行方法

针对第一部分:简单来说就是访问权限检查,判断你是否可以访问这个方法

具体来说就是: 检查override,如果override为true,(Method的父类AccessibleObject中声明的变量)跳过检查;否则继续; 快速检查,判断该方法的修饰符modifiers是否为public,如果是跳过检查;否则继续; 详细检查,通过方法的(protected/private/package)修饰符或方法的声明类(例如子类可以访问父类的protected方法)与调用者caller之间的关系,判断caller是否有权限访问该方法。这里推荐看一下java四种访问权限,可能我们一般只用到private和public,但访问权限控制很重要,在一些多人合作的项目中尤为重要 

这里就涉及到一个有意思的 Field(他父类也是AccessibleObject),他的override是false,导致我们在获取属性是常用setAccessible(true),当属性为private修饰

针对第二部分MethodAccessor.invoke();也就是真正的调用方法 

这里有一个注释  // read volatile,这个很有意思是,volatile 是一个类型修饰符。volatile 的作用是作为指令关键字,确保本条指令不会因编译器的优化而省略。//这是methodAccessor,对应的代码private volatile MethodAccessor methodAccessor;
    
        MethodAccessor tmp =  (root != ) tmp = (tmp != =
            tmp = reflectionFactory.newMethodAccessor(
    =
         (root != //这个方法可能会导致类膨胀
//类膨胀:类的膨胀(Bloating)指的是类中成员过多,甚至出现无序增加的情况。过大的类,会使得复杂度急剧增加,维护会变得更为困难。所以需要控制类的增长。
//,这篇文章讲解类膨胀= = =
注意这个方法acquireMethodAccessor,他有一个调用反射工厂的过程,ReflectionFactory利用MethodAccessor的字节码生成类MethodAccessorGenerator直接创建一个代理类,通过间接调用原方法完成invoke()任务;
这句话有几个概念:字节码,动态代理,反射最终都是调用原始类
这些遗留问题日后在解决把!!!

 

7:总结一下我理解的反射和应用场景

(1)反射的概念:可以理解成你去了一个小黑屋,里面可能有各种东西,都上了锁,你通过反射就能获取里面的东西,并且去除锁,知道东西的真正面目

(2)反射应用场景:简单来说就是“动态带有固定”,举个例子,比如我上面的例子,方法是动态的,但是方法的参数是固定的;传入的参数固定的,但是顺序未必和方法一致的; 

 

 

【版权声明】本文内容来自摩杜云社区用户原创、第三方投稿、转载,内容版权归原作者所有。本网站的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@moduyun.com

  1. 分享:
最后一次编辑于 2023年11月15日 0

暂无评论

TEZNKK3IfmPf