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(); } } }