【修真院java小课堂】Java反射机制

一、反射机制的概念

       JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
要想解剖一个类,必须先要获取到该类的字节码文件对象。而解剖使用的就是Class类中的方法.所以先要获取到每一个字节码文件对应的Class类型的对象.
      一般情况,java程序在运行的时候,会先通过Bootstrap ClassLoader 最顶层的加载类,主要加载核心类库,%JRE_HOME%\lib下的jar包;
Extention ClassLoader 扩展的类加载器,加载目录%JRE_HOME%\lib\ext目录下的jar包和class文件;Appclass Loader也称为SystemAppClass 加载当前应用的classpath的所有类,即自己写的经过编译过后的字节码文件。在程序运行过程中,实例化对象是,就将对应的加载了的类对象存方到堆内存之中,以供使用,如下图:

      如果需要使用编译时没有被编译的类(也就是运行时没有被jvm加载到内存之中的类),获取类中的各种信息,java反射机制能够实现这种功能。

二、使用反射机制的步骤

(1)获取类的class文件;

(2)通过class文件获取类中的方法、变量等信息;

(3)使用反射API来操作这些信息。

       其中获取class文件有三种方式。第一种是对象名.getClass(),需要有此类的实例化对象才能用,但是如果已经有对象了,可以直接调用类中的方法和属性了,再通过反射来获取的话就多此一举了;第二种是类名.class,需要导入类所在的包,用起来较为繁琐;第三种是通过Class类的静态方法forName()获取,常用这种方法,因为只需要输入类名的字符串即可。

三、代码示例

public class TestReflect {
    private Class c;

    {
        try {
            c = Class.forName("com.enroll.POJO.EntryForm");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

    @Test
    public void constructorTest() throws Exception {
        //get c.class
        Class c = Class.forName("com.enroll.POJO.EntryForm");
        //get a constructor with no parameterType
        Constructor constructor = c.getConstructor();
        System.out.println(constructor + "\n");
        Constructor[] constructors = c.getConstructors();
        //get all constructors
        for (Constructor constructor1 : constructors)
            System.out.println(constructor1);
        System.out.println();
        //get a constructor with String/Integer parameterType
        Constructor constructor1 = c.getConstructor(String.class, int.class);
        System.out.println(constructor1 + "\n");
    }

    @Test
    public void methodTest() throws Exception {

        //all methods
        Method[] methods = c.getDeclaredMethods();
        //too many to show
        System.out.println(methods.length);
        //get setName()
        Method method = c.getMethod("setName", String.class);
        System.out.println(method);
    }

    @Test
    public void fieldTest() throws Exception {
        //get all fields include private field
        Field[] fields = c.getDeclaredFields();
        System.out.println(fields.length);
        //public field
        Field[] fields1 = c.getFields();
        for (Field field : fields1)
            System.out.println(field);
        //get String test1  throws Exception
        Field field = c.getField("test");
        System.out.println(field);

    }

    @Test
    public void reflectTest() throws Exception {
        //new object  throws Exception
        Object o = c.newInstance();
        Method method = c.getMethod("reflect", String.class);
//        method.setAccessible(true);
        System.out.println(method.invoke(o, "123456"));

    }

}

四、暴力反射

        如何获取和使用类中的私有属性和方法呢?答案是通过“暴力反射”。反射里的Constructor,Field,Method三个类都有一个getDeclaredXxx方法,可以不受权限控制的获取类的构造函数,字段,方法,如果想要私有构造函数创建对象,字段赋值,方法调用的话,会自动的访问类的isAccessable,默认的是false,所以,你要想访问类中的私有成员的时候,就要调用setAccessable方法,将其改为true,这样就可以对类中的私有成员进行操作了。

猜你喜欢

转载自blog.csdn.net/qq_41810013/article/details/80165328