反射3--Method,简单的实现和部分源码分析

public class Person {

    private int age;
    public String name;

    public Person(){};

    public Person(String name) {
        this.name = name;
        System.out.println(this.name);
    }

    public Person(int age, String name) {
        this(name);
        this.age = age;
    }

    public int getAge() {
        return age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void getInfo() {
        System.out.println("name:" + name + "; age:" + age);
    }

    public void setNum(double x) {
        x = 3 * x;
    }

    public void firstMethod(){
        System.out.println("This is first method");
    }

    private void secondMethod(){
        System.out.println("This is second method");
    }

    private String ThirdMethod(String arg){
        return "This is third method"+arg;
    }
}
public class reflectTest {
    public static void main(String[] args) throws Exception {
        //1. 实例化Person
        Person person = (Person)Class.forName("POJO.Person").newInstance();

        //2. getDeclaredMethod()获取方法
        Method method = person.getClass().getDeclaredMethod("firstMethod");

        //3. method.getModifiers()获取方法做用域,method.getName()获取方法名
        System.out.println("fitst method:"+Modifier.toString(method.getModifiers())+" "+method.getName()+" ");

        //4. invoke注入方法对象
        method.invoke(person);
    }
}

执行后输出:java

fitst method:public firstMethod 
This is first method

依然是看一下源码安全

public Method getDeclaredMethod(String name, Class<?>... parameterTypes)
        throws NoSuchMethodException, SecurityException {

        //1.依然是先进行java的安全验证和权限验证,具体参考上一章,
        //private的方法会抛异常(java.lang.IllegalAccessException)
        checkMemberAccess(Member.DECLARED, Reflection.getCallerClass(), true);

        //2.searchMethods将在,privateGetDeclaredMethods返回的方法(Method[])中,
        //查找一个name(名称),和parameterTypes(参数类型)匹配的方法
        Method method = searchMethods(privateGetDeclaredMethods(false), name, parameterTypes);

        if (method == null) {
            throw new NoSuchMethodException(getName() + "." + name + argumentTypesToString(parameterTypes));
        }
        return method;
    }
@CallerSensitive
    public Object invoke(Object obj, Object... args)
        throws IllegalAccessException, IllegalArgumentException,
           InvocationTargetException
    {
        if (!override) {
            //1. quickCheckMemberAccess进行权限检查,若是是public,跳出if判断
            //若是不是public,则获取这个类(参考上一章),以后对这个类进行判断
            if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
                Class<?> caller = Reflection.getCallerClass();
                checkAccess(caller, clazz, obj, modifiers);
            }
        }

        //再由MethodAccessor对象来调用invoke方法,具体往下看
        MethodAccessor ma = methodAccessor;             // read volatile
        if (ma == null) {
            ma = acquireMethodAccessor();
        }
        return ma.invoke(obj, args);
    }

MethodAccessor 是个啥玩意?
我也不知道,源码中也并无写更多注释,但网络上的一篇文章解释了这个对象网络

https://www.sczyh30.com/posts/Java/java-reflection-2/
其中做者解释了使用这个对象的缘由ide

每一个Java方法有且只有一个Method对象做为root,它至关于根对象,对用户不可见。当咱们建立Method对象时,咱们代码中得到的Method对象都至关于它的副本(或引用)。root对象持有一个MethodAccessor对象,因此全部获取到的Method对象都共享这一个MethodAccessor对象,所以必须保证它在内存中的可见性。
时序图post

invoke底层会经过jni去调用.dll动态连接库的方法invoke0来实现方法的调用,native实际上是在JVM的栈中找到这个方法,而后经过方法实例根据参数进行方法运行ui

相关文章
相关标签/搜索