反射(三)之 获取并执行父类中定义的私有方法

一、获取当前类的父类:直接调用Class对象的getSuperClass()方法

package test.com.atguigu.javase.lesson12; 

import org.junit.Test;

/**
 * 获取当前类的父类
 * 直接调用Class对象的getSuperClass()方法
 * @throws Exception
 */
public class GetSuperClassTestTest { 

    @Test
    public void testGetSuperClass() throws Exception {
        String className = "com.atguigu.javase.lesson12.Student";
        Class clazz = Class.forName(className);
        Class superClazz = clazz.getSuperclass();
        System.out.println(superClazz);
    }
} 

二、若需要通过反射执行私有方法,需要method.setAccessible(true)这一步操作

Student类:

package com.atguigu.javase.lesson12;

public class Student extends Person {
    private void method1(Integer age){
        System.out.println("private void method1");
    }
}

InvokePrivateMethodTest类

package test.com.atguigu.javase.lesson12; 

import com.atguigu.javase.lesson12.Student;
import org.junit.Test;
import java.lang.reflect.Method;

public class InvokePrivateMethodTestTest {

    /**
     * 若通过Method的invoke()方法调用方法,而访问权限不足,则可以先使该方法变为可访问的:
     * method.setAccessible(true)
     *
     * @throws Exception
     */
    @Test
    public void testInvokePrivateMethod() throws Exception {
        Object obj = new Student();
        Class clazz = obj.getClass();
        Method method = clazz.getDeclaredMethod("method1",Integer.class);
        System.out.println(method);
        //若通过反射执行私有方法
        method.setAccessible(true);
        method.invoke(obj,10);
    }
} 

三、获取父类中私有方法,采用循环向上转型的方式获得

Person类:

package com.atguigu.javase.lesson12;

public class Person {
    String name;
    private int age;

    private void test() {

    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
        System.out.println("name:" + name);
    }

    public void setName(String name, Integer age) {
        this.name = name;
        this.age = age;
        System.out.println("name:" + name);
        System.out.println("age:" + age);
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public Person(String name, int age) {
        super();
        this.name = name;
        this.age = age;
        System.out.println("有参数的构造器");
    }

    public Person() {
        System.out.println("无参数的构造器");
    }

    private String method2() {
        return "private String method2";
    }
}

UtilTest类:

package test.com.atguigu.javase.lesson12;

import com.atguigu.javase.lesson12.Student;
import org.junit.Test;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class UtilTestTest {

    /**
     * 既可以访问本类私有方法, 也可以访问父类的私有方法
     *
     * @param obj        放法执行的那个对象
     * @param methodName 类的一个方法的方法名该方法也可能是私有方法
     * @param args       调用该方法需要传入的参数
     * @return 调用方法后的返回值
     * @throws NoSuchMethodException
     */
    public Object invoke(Object obj, String methodName, Object... args) throws NoSuchMethodException {
        Class clazz = obj.getClass();
        Class[] parameterTypes = new Class[args.length];
        for (int i = 0; i < args.length; i++) {
            parameterTypes[i] = args[i].getClass();
        }
        Method method = getMethod(clazz, methodName, parameterTypes);
        method.setAccessible(true);
        try {
            return method.invoke(obj, args);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 获取clazz的methodName方法,该方法可能是私有方法,还可能是父类中的私有方法
     *
     * @param clazz
     * @param methodName
     * @param parameterTypes
     * @return
     */
    public Method getMethod(Class clazz, String methodName, Class... parameterTypes) {
        for (; clazz != Object.class; clazz = clazz.getSuperclass()) {
            try {
                Method method = clazz.getDeclaredMethod(methodName, parameterTypes);
                return method;
            } catch (Exception e) {

            }
        }
        return null;
    }

    @Test
    public void testInvoke() throws NoSuchMethodException {
        Object obj = new Student();
        invoke(obj, "method1", 10);
        Object object = invoke(obj, "method2");
        System.out.println(object);
    }

    @Test
    public void testGetMethod() throws ClassNotFoundException {
        Class clazz = Class.forName("com.atguigu.javase.lesson12.Student");
        Method method = getMethod(clazz, "method1", Integer.class);
        System.out.println(method);

        method = getMethod(clazz, "method2");
        System.out.println(method);
    }
} 

四、练习

package test.com.atguigu.javase.lesson12;

import com.atguigu.javase.lesson12.Student;
import org.junit.Test;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class UtilTestTest {

    /**
     * 既可以访问本类私有方法, 也可以访问父类的私有方法
     *
     * @param obj        放法执行的那个对象
     * @param methodName 类的一个方法的方法名该方法也可能是私有方法
     * @param args       调用该方法需要传入的参数
     * @return 调用方法后的返回值
     * @throws NoSuchMethodException
     */
    public Object invoke(Object obj, String methodName, Object... args) throws NoSuchMethodException {
        Class clazz = obj.getClass();
        Class[] parameterTypes = new Class[args.length];
        for (int i = 0; i < args.length; i++) {
            parameterTypes[i] = args[i].getClass();
        }
        Method method = getMethod(clazz, methodName, parameterTypes);
        method.setAccessible(true);
        try {
            return method.invoke(obj, args);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 获取clazz的methodName方法,该方法可能是私有方法,还可能是父类中的私有方法
     *
     * @param clazz
     * @param methodName
     * @param parameterTypes
     * @return
     */
    public Method getMethod(Class clazz, String methodName, Class... parameterTypes) {
        for (; clazz != Object.class; clazz = clazz.getSuperclass()) {
            try {
                Method method = clazz.getDeclaredMethod(methodName, parameterTypes);
                return method;
            } catch (Exception e) {

            }
        }
        return null;
    }

    @Test
    public void testInvoke() throws NoSuchMethodException {
        Object obj = new Student();
        invoke(obj, "method1", 10);
        Object object = invoke(obj, "method2");
        System.out.println(object);
    }

    @Test
    public void testGetMethod() throws ClassNotFoundException {
        Class clazz = Class.forName("com.atguigu.javase.lesson12.Student");
        Method method = getMethod(clazz, "method1", Integer.class);
        System.out.println(method);

        method = getMethod(clazz, "method2");
        System.out.println(method);
    }

    /**
     *
     */
    @Test
    public void testClassMethod() throws ClassNotFoundException, IllegalAccessException, InstantiationException, InvocationTargetException {
        //全类名
        String className = "com.atguigu.javase.lesson12.Student";
        //方法名,可能在上一步给的类中,也可能在父类中,可能私有,可能共有
        String methodName = "method3";
        //执行上一步对应的方法时需要传入的参数列表
        Object[] args = {"Jerry", 24};

        //根据以上条件,执行methodName对应的方法,并打印返回值

        //1.加载className对应的类,获取对应的Class对应clazz
        Class clazz = Class.forName(className);

        //2.调用clazz的getDeclaredMethod()方法获取对应的Method对象
        //注意:
        //2.1 因为该方法可能不在当前类中,所以有可能去父类中获取
        //2.2 因为给定的条件中并没有给定参数类型的列表,需要从args来获取参数类型的列表
        Class[] parameterTypes = new Class[args.length];
        for (int i = 0; i < args.length; i++) {
            parameterTypes[i] = args[i].getClass();
        }
        Method method = null;
        for (Class clazz2 = clazz; clazz2 != Object.class; clazz2 = clazz2.getSuperclass()) {
            try {
                method = clazz2.getDeclaredMethod(methodName, parameterTypes);
            } catch (NoSuchMethodException e) {

            }
        }

        //3.因为Method可能是私有的,所以需要让其变为可被访问:setAccessible(true)
        method.setAccessible(true);

        //4. 调用Method
        //4.1 利用1得到的clazz先创建className对应的类的一个对象
        Object obj = clazz.newInstance();
        //4.2 再调用Method的invoke()方法执行方法
        Object result = method.invoke(obj, args);
        System.out.println(result);
    }
} 

猜你喜欢

转载自blog.csdn.net/ada_yangyang/article/details/81005519