欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Java SE之反射回顾

程序员文章站 2022-06-09 21:12:15
...
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * @author Kevin 2018-2-8
 * 
 * 
 * 
 * 看 tomcat源码发现,很多地方用到了反射,回顾一下Method的用法,及其参数的意义。
 * 
 * 反射的基本操作流程是:
 * 1.获取一个类加载器ClassLoader;
 * 2.获取Class的类信息,调用类加载器的loadClass方法,参数为String类型(全限定名);
 * 3.获取类实例;
 * 4.进行相关属性或者方法的操作。
 * 
 * Method对象,是对类方法的封装,调用用invoke方法
 *
 * Class.getMethod(String name, Class<?>... parameterTypes)
 *      --name:方法名称
 *      --参数列表,参数类型的class,如果没有参数的话就传null
 * 
 * Method.invoke(Object obj, Object... args) 
 *      --obj:调用方法的类的实例对象
 *      --args:n个参数,对应方法,如果没有参数传null
 */
public class MethodDemo {

    public static void main(String[] args)  {

        try {
            ClassLoader cl = new MethodDemo().getClass().getClassLoader();
            Class<?> carclass = cl.loadClass("com.reflect.demo.Car");

            Object o = carclass.getConstructor().newInstance();
            Class<?>[] p = new Class<?>[1];
            p[0] = String.class;
            Method m = o.getClass().getMethod("setColor",p);
            m.invoke(o, "红色");


            Method m2 = o.getClass().getMethod("driver",null);
            m2.invoke(o, null);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (SecurityException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        }

    }

}
public class Car {

    private String color;


    public String getColor() {
        return color;
    }


    public void setColor(String color) {
        this.color = color;
        System.out.println(color);
    }


    public void driver() {
        System.out.println("直行中......");
    }
}

下面来看一个Tomcat中随处可见的反射使用,如Bootstrap启动类的init方法中就反射生成了
Catalina类,调用它的setParentClassLoader方法设置父类加载器:

public void init() throws Exception {

        initClassLoaders();

        Thread.currentThread().setContextClassLoader(catalinaLoader);

        SecurityClassLoad.securityClassLoad(catalinaLoader);

        // Load our startup class and call its process() method
        if (log.isDebugEnabled())
            log.debug("Loading startup class");
        Class<?> startupClass = catalinaLoader.loadClass("org.apache.catalina.startup.Catalina");
        Object startupInstance = startupClass.getConstructor().newInstance();

        // Set the shared extensions class loader
        if (log.isDebugEnabled())
            log.debug("Setting startup class properties");
        String methodName = "setParentClassLoader";
        Class<?> paramTypes[] = new Class[1];
        paramTypes[0] = Class.forName("java.lang.ClassLoader");
        Object paramValues[] = new Object[1];
        paramValues[0] = sharedLoader;
        Method method =
            startupInstance.getClass().getMethod(methodName, paramTypes);
        method.invoke(startupInstance, paramValues);

        catalinaDaemon = startupInstance;

    }