Java 反射,就是在运行状态中。

  • 获取任意类的名称、package信息、所有属性、方法、注解、类型、类加载器等
  • 获取任意对象的属性,并且能改变对象的属性
  • 调用任意对象的方法
  • 判断任意一个对象所属的类
  • 实例化任意一个类的对象
    Java 的动态就体现在这。通过反射我们可以实现动态装配,降低代码的耦合度;动态代理等。反射的过度使用会严重消耗系统资源。
    JDK 中 java.lang.Class 类,就是为了实现反射提供的核心类之一。
    下面列举一些反射的几个主要函数:
package try1;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

/**
 * 反射的基础方法
 *2019/11/13
 **/
public class Try {
    public static void main(String[] args) {
        Example e1 = new Example();
//        System.out.println(e1.getClassMethod1().getName());
//        System.out.println(e1.getClassMethod2().getName());
//        System.out.println(e1.getClassMethod3().getName());
        e1.geMethods();
    }
}
class Example{
    /**
     *  方式一.通过类的getClass()方法
     *  都已经得到对象了,反射显得多余
     **/
    public Class getClassMethod1(){
        ManDemo md = new ManDemo();
        return md.getClass();
    }
    /**
     *  方式二.通过类的.class 获取
     *  强依赖,需要引入相关类
     **/
    public Class getClassMethod2(){
//        ManDemo md = new ManDemo();
        return ManDemo.class;
    }

    /**
     *  方式三.通过 Class.forName("") 获取
     *  灵活 首要选择
     *  这里需要注意,通过类的全路径名获取Class对象会抛出一个异常,如果根据类路径找不到这个类那么就会抛出这个异常。
     **/
    public Class getClassMethod3(){
        Class c = null;
        try {
            c = Class.forName("try1.ManDemo");
            c.getName();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        return c;
    }

    /**
     * 类装载器 ClassLoader
     * ClassLoader是一个重要的Java运行时系统组件,负责在运行时查找和装载Class字节码文件
     * JVM运行时会产生3个:
     * ClassLoader:根装载器 、 ExtClassLoader 扩展类装载器 、AppClassLoader应用类装载器
     * 其中根装载器是C++中的方法 ,故在java中看不到它,无法获取句柄
     * 根装载器负责装载JRE的核心类库,ExtClassLoader扩展类装载器 和 AppClassLoader应用类装载器都是ClassLoader的子类
     * ExtClassLoader负责装载JRE扩展目录ext中的JAR类包;
     * AppClassLoader负责装载Classpath路径下的类包
     * 由于 全盘负责委托机制 的存在 故优先父级加载
     *
     **/
    public Class getClassMethod4(){
        ClassLoader loader = Thread.currentThread().getContextClassLoader();
        Class c = null;
        try{
            c = loader.loadClass("try1.ManDemo");
        }catch (Exception e){
            e.printStackTrace();
        }
        return c;
    }

    /**
     * 获取构造方法
     * @Date 2019/11/14
     **/
    public void getConstructors(){
        Class c = getClassMethod3();
        //获取所有构造方法
        System.out.println("----------获取所有public构造方法-----------");
        Constructor[] constructors = c.getConstructors();
        for (Constructor cc:constructors) {
            System.out.println(cc);
        }
        System.out.println("----------获取所有声明过的构造方法-----------");
        Constructor[] constructors2 = c.getDeclaredConstructors();
        for (Constructor cc:constructors2) {
            System.out.println(cc);
        }
        try {
            System.out.println("----------获取共有单独构造方法-----------");
            System.out.println( c.getConstructor(String.class,Integer.class));
            System.out.println( c.getConstructor(Integer.class,String.class));
            System.out.println( c.getConstructor());


            System.out.println("----------获取单独所有声明过的构造方法-----------");
            System.out.println( c.getDeclaredConstructor(String.class));
            System.out.println( c.getDeclaredConstructor(Integer.class,String.class));

        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }
    }
    /**
     * 获取类属性
     * @Date 2019/11/14
     **/
    public void getFields(){
        Class c = getClassMethod3();
        System.out.println("----------获取所有共有字段------------");
        Field[] fields = c.getFields();
        for (Field f: fields) {
            System.out.println(f);
        }
        System.out.println("----------获取所有声明过的字段------------");
        Field[] fields1 = c.getDeclaredFields();
        for (Field f: fields1) {
            System.out.println(f);
        }
        System.out.println("----------获取共有字段并使用-----------");
        try {
            //获得指定的共有字段
            Field field = c.getField("sex");
            //获取一个公有构造方法,并实例化
            Object obj = c.getConstructor().newInstance();
            //为属性设置值
            field.set(obj,true);
            ManDemo man = (ManDemo)obj;
            System.out.println(man.sex);
        } catch (Exception e) {
            e.printStackTrace();
        }
        System.out.println("----------获取私有字段并使用-----------");
        try {
            Field nameField = c.getDeclaredField("name");
            Object obj2 = c.getConstructor().newInstance();
            //设置暴力反射 允许修改私有字段 否则修改私有字段会产生异常
            nameField.setAccessible(true);
            nameField.set(obj2,"王舞");
            ManDemo man = (ManDemo)obj2;
            System.out.println(man.getName());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 获取类中方法
     * @Date 2019/11/14
     **/
    public void geMethods(){
        Class c = getClassMethod3();
        System.out.println("----------获取所有共有方法------------");
        Method[] methods = c.getMethods();
        for (Method m:methods) {
            System.out.println(m);
        }

        Method[] methods1 = c.getDeclaredMethods();
        System.out.println("----------获取所有方法------------");
        for (Method m:methods1) {
            System.out.println(m);
        }
        try {
            Object obj = c.getConstructor().newInstance();

            System.out.println("----------获取特定的方法并使用(不带参)------------");
            Method m = c.getMethod("sleep");
            m.invoke(obj);
            System.out.println("----------获取特定的方法并使用(不带参、私有)------------");
            Method m1 =  c.getDeclaredMethod("think");
            m1.setAccessible(true);
            m1.invoke(obj);
            System.out.println("----------获取特定的方法并使用(带参)------------");
            Method m2 =  c.getDeclaredMethod("eat1",String.class);
            m2.invoke(obj,"杨梅");
            c.getDeclaredMethod("drunk",String.class,Integer.class).invoke(obj,"橙汁",3);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}