java中的反射通过类的字节码class文件,获取到class对象,通过class对象可以获取类的信息(类名字,类属性,类方法,类构造器)。

一个类在被加载后,jvm会创建一个对应该类的Class对象,类的整个结构信息会放到对应的Class对象中。这个Class对象就像一面镜子,通过这面镜子可以看到对应类的全部信息。

 

测试的JavaBean方法如下:

package com.mg.java.maven.day05;

public class Student {
    private int id;
    private int age;
    private String uname;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public int getAge() {
        return age;
    }

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

    public String getUname() {
        return uname;
    }

    public void setUname(String uname) {
        this.uname = uname;
    }

    public Student() {
        super();
        // TODO Auto-generated constructor stub
    }

    public Student(int id, int age, String uname) {
        super();
        this.id = id;
        this.age = age;
        this.uname = uname;
    }

}

反射调用方法实现步骤:

第一步:获取字节码(2种方式):

 

获取字节码

package com.mg.java.maven.day05;

/**
 * 测试java.lang.Class对象的获取方式
 * 
 * @author admin
 *
 */
public class ReflectDemo01 {
    public static void main(String[] args) {
        String path = "com.mg.java.maven.day05.Student";
        try {
            // 第一种:通过路径获取字节码
            Class<?> clazz = Class.forName(path);
            // 一个类被加载后,jvm会创建一个对应该类的Class对象,类的整个结构信息会放到对应的Class对象中。
            // 这个Class对象就像一面镜子,通过这面镜子可以看到对应类的全部信息。
            System.out.println(clazz);
            
            // 第二种:通过类名去获取
            Class<?> clazz1 = Student.class;
            System.out.println(clazz1);

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

通过反射API获取类的信息(类名字,类属性,类方法,类构造器):

package com.mg.java.maven.day05;

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

/**
 * 应用反射API,获取类的信息(类名字,类属性,类方法,类构造器)
 * 
 * @author admin
 *
 */
public class ReflectDemo02 {
    public static void main(String[] args) {
        String path = "com.mg.java.maven.day05.Student";

        try {
            Class<?> clazz = Class.forName(path);

            // 获取类名
            System.out.println(clazz.getName()); // 获取包名+类名
            System.out.println(clazz.getSimpleName()); // 获取类名

            // 获取类属性
            // 获得所有的field
            Field[] fields = clazz.getDeclaredFields();
            for (Field field : fields) {
                System.out.println("属性:" + field);
            }

            // 获取指定的field
            Field f = clazz.getDeclaredField("uname");
            System.out.println(f);

            // 获取方法
            // 获取所有的method
            Method[] methods = clazz.getDeclaredMethods();
            for (Method method : methods) {
                System.out.println("方法:" + method);
            }

            // 获取指定的method
            // 如果方法有参数,则必须传递参数类型对应的Class对象
            Method m = clazz.getDeclaredMethod("setUname", String.class);
            System.out.println(m);

            // 获取构造器
            // 获取所有的构造器
            Constructor<?>[] constructors = clazz.getDeclaredConstructors();
            for (Constructor<?> constructor : constructors) {
                System.out.println("构造器:" + constructor);
            }

            // 获取指定的构造器
            // 如果方法有参数,则必须传递参数类型对应的Class对象
            Constructor<?> constructors2 = clazz.getDeclaredConstructor(int.class, int.class, String.class);
            System.out.println(constructors2);

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

通过字节码去创建对象,调用newInstance()方法,反射API动态调用:构造器,方法,属性:

package com.mg.java.maven.day05;

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

/**
 * 反射API动态调用:构造器,方法,属性
 * 
 * @author admin
 *
 */
public class ReflectDynamicInvoke {
    /* 反射动态调用 */
    public static void main(String[] args) {
        String path = "com.mg.java.maven.day05.Student";
        try {
            Class<Student> clazz = (Class<Student>) Class.forName(path);

            // 通过反射API调用构造器,构造对象
            Student student1 = clazz.newInstance(); // 调用了Student的无参构造方法
            System.out.println(student1);

            // 调用有参构造方法
            Constructor<?> constructor = clazz.getConstructor(int.class, int.class, String.class);
            Student student2 = (Student) constructor.newInstance(1001, 20, "张三");
            System.out.println(student2.getUname());

            // 通过反射API调用普通方法
            Student student3 = clazz.newInstance();
            Method method = clazz.getDeclaredMethod("setUname", String.class);
            method.invoke(student3, "李四"); // 相当于student3.setUname("李四");
            System.out.println(student3.getUname());

            // 通过反射AP操作属性
            Student student4 = clazz.newInstance();
            Field field = clazz.getDeclaredField("uname");
            field.setAccessible(true); // 反射访问私有属性,不用做安全检查,直接访问。
            field.set(student4, "王五"); // 通过反射写属性
            System.out.println(student4.getUname());
            System.out.println(field.get(student4)); // 通过反射读属性

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}