-
package com.hspedu.reflection;import org.junit.jupiter.api.Test;import java.lang.annotation.Annotation; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Method;/*** @author 韩顺平* @version 1.0* 演示如何通过反射获取类的结构信息*/ public class ReflectionUtils {public static void main(String[] args) {}@Testpublic void api_02() throws ClassNotFoundException, NoSuchMethodException {//得到Class对象Class<?> personCls = Class.forName("com.hspedu.reflection.Person");//getDeclaredFields:获取本类中所有属性//规定 说明: 默认修饰符 是0 , public 是1 ,private 是 2 ,protected 是 4 , static 是 8 ,final 是 16Field[] declaredFields = personCls.getDeclaredFields();for (Field declaredField : declaredFields) {System.out.println("本类中所有属性=" + declaredField.getName()+ " 该属性的修饰符值=" + declaredField.getModifiers()+ " 该属性的类型=" + declaredField.getType());}//getDeclaredMethods:获取本类中所有方法Method[] declaredMethods = personCls.getDeclaredMethods();for (Method declaredMethod : declaredMethods) {System.out.println("本类中所有方法=" + declaredMethod.getName()+ " 该方法的访问修饰符值=" + declaredMethod.getModifiers()+ " 该方法返回类型" + declaredMethod.getReturnType());//输出当前这个方法的形参数组情况Class<?>[] parameterTypes = declaredMethod.getParameterTypes();for (Class<?> parameterType : parameterTypes) {System.out.println("该方法的形参类型=" + parameterType);}}//getDeclaredConstructors:获取本类中所有构造器Constructor<?>[] declaredConstructors = personCls.getDeclaredConstructors();for (Constructor<?> declaredConstructor : declaredConstructors) {System.out.println("====================");System.out.println("本类中所有构造器=" + declaredConstructor.getName());//这里老师只是输出名Class<?>[] parameterTypes = declaredConstructor.getParameterTypes();for (Class<?> parameterType : parameterTypes) {System.out.println("该构造器的形参类型=" + parameterType);}}}//第一组方法API@Testpublic void api_01() throws ClassNotFoundException, NoSuchMethodException {//得到Class对象Class<?> personCls = Class.forName("com.hspedu.reflection.Person");//getName:获取全类名System.out.println(personCls.getName());//com.hspedu.reflection.Person//getSimpleName:获取简单类名System.out.println(personCls.getSimpleName());//Person//getFields:获取所有public修饰的属性,包含本类以及父类的Field[] fields = personCls.getFields();for (Field field : fields) {//增强forSystem.out.println("本类以及父类的属性=" + field.getName());}//getDeclaredFields:获取本类中所有属性Field[] declaredFields = personCls.getDeclaredFields();for (Field declaredField : declaredFields) {System.out.println("本类中所有属性=" + declaredField.getName());}//getMethods:获取所有public修饰的方法,包含本类以及父类的Method[] methods = personCls.getMethods();for (Method method : methods) {System.out.println("本类以及父类的方法=" + method.getName());}//getDeclaredMethods:获取本类中所有方法Method[] declaredMethods = personCls.getDeclaredMethods();for (Method declaredMethod : declaredMethods) {System.out.println("本类中所有方法=" + declaredMethod.getName());}//getConstructors: 获取所有public修饰的构造器,包含本类Constructor<?>[] constructors = personCls.getConstructors();for (Constructor<?> constructor : constructors) {System.out.println("本类的构造器=" + constructor.getName());}//getDeclaredConstructors:获取本类中所有构造器Constructor<?>[] declaredConstructors = personCls.getDeclaredConstructors();for (Constructor<?> declaredConstructor : declaredConstructors) {System.out.println("本类中所有构造器=" + declaredConstructor.getName());//这里老师只是输出名}//getPackage:以Package形式返回 包信息System.out.println(personCls.getPackage());//com.hspedu.reflection//getSuperClass:以Class形式返回父类信息Class<?> superclass = personCls.getSuperclass();System.out.println("父类的class对象=" + superclass);////getInterfaces:以Class[]形式返回接口信息Class<?>[] interfaces = personCls.getInterfaces();for (Class<?> anInterface : interfaces) {System.out.println("接口信息=" + anInterface);}//getAnnotations:以Annotation[] 形式返回注解信息Annotation[] annotations = personCls.getAnnotations();for (Annotation annotation : annotations) {System.out.println("注解信息=" + annotation);//注解}} }class A {public String hobby;public void hi() {}public A() {}public A(String name) {} }interface IA { }interface IB {}@Deprecated class Person extends A implements IA, IB {//属性public String name;protected static int age; // 4 + 8 = 12String job;private double sal;//构造器public Person() {}public Person(String name) {}//私有的private Person(String name, int age) {}//方法public void m1(String name, int age, double sal) {}protected String m2() {return null;}void m3() {}private void m4() {} }
-
通过反射创建对象
package com.hspedu.reflection;import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException;/*** @author 韩顺平* @version 1.0* 演示通过反射机制创建实例*/ public class ReflecCreateInstance {public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {//1. 先获取到User类的Class对象Class<?> userClass = Class.forName("com.hspedu.reflection.User");//2. 通过public的无参构造器创建实例Object o = userClass.newInstance();System.out.println(o);//3. 通过public的有参构造器创建实例/*constructor 对象就是public User(String name) {//public的有参构造器this.name = name;}*///3.1 先得到对应构造器Constructor<?> constructor = userClass.getConstructor(String.class);//3.2 创建实例,并传入实参Object hsp = constructor.newInstance("hsp");System.out.println("hsp=" + hsp);//4. 通过非public的有参构造器创建实例//4.1 得到private的构造器对象Constructor<?> constructor1 = userClass.getDeclaredConstructor(int.class, String.class);//4.2 创建实例//暴破【暴力破解】 , 使用反射可以访问private构造器/方法/属性, 反射面前,都是纸老虎constructor1.setAccessible(true);Object user2 = constructor1.newInstance(100, "张三丰");System.out.println("user2=" + user2);} }class User { //User类private int age = 10;private String name = "韩顺平教育";public User() {//无参 public}public User(String name) {//public的有参构造器this.name = name;}private User(int age, String name) {//private 有参构造器this.age = age;this.name = name;}public String toString() {return "User [age=" + age + ", name=" + name + "]";} }
-
反射爆破操作属性
package com.hspedu.reflection;import java.lang.reflect.Field;/*** @author 韩顺平* @version 1.0* 演示反射操作属性*/ public class ReflecAccessProperty {public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchFieldException {//1. 得到Student类对应的 Class对象Class<?> stuClass = Class.forName("com.hspedu.reflection.Student");//2. 创建对象Object o = stuClass.newInstance();//o 的运行类型就是StudentSystem.out.println(o.getClass());//Student//3. 使用反射得到age 属性对象Field age = stuClass.getField("age");age.set(o, 88);//通过反射来操作属性System.out.println(o);//System.out.println(age.get(o));//返回age属性的值//4. 使用反射操作name 属性Field name = stuClass.getDeclaredField("name");//对name 进行暴破, 可以操作private 属性name.setAccessible(true);//name.set(o, "老韩");name.set(null, "老韩~");//因为name是static属性,因此 o 也可以写出null//null是所有对象的System.out.println(o);System.out.println(name.get(o)); //获取属性值System.out.println(name.get(null));//获取属性值, 要求name是static} }class Student {//类public int age;private static String name;public Student() {//构造器}public String toString() {return "Student [age=" + age + ", name=" + name + "]";} }
package com.hspedu.reflection;import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method;/*** @author 韩顺平* @version 1.0* 演示通过反射调用方法*/ public class ReflecAccessMethod {public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException {//1. 得到Boss类对应的Class对象Class<?> bossCls = Class.forName("com.hspedu.reflection.Boss");//2. 创建对象Object o = bossCls.newInstance();//3. 调用public的hi方法//Method hi = bossCls.getMethod("hi", String.class);//OK//3.1 得到hi方法对象Method hi = bossCls.getDeclaredMethod("hi", String.class);//OK//3.2 调用hi.invoke(o, "韩顺平教育~");//4. 调用private static 方法//4.1 得到 say 方法对象Method say = bossCls.getDeclaredMethod("say", int.class, String.class, char.class);//4.2 因为say方法是private, 所以需要暴破,原理和前面讲的构造器和属性一样say.setAccessible(true);System.out.println(say.invoke(o, 100, "张三", '男'));//4.3 因为say方法是static的,还可以这样调用 ,可以传入nullSystem.out.println(say.invoke(null, 200, "李四", '女'));//5. 在反射中,如果方法有返回值,统一以Object来接收 , 但是他运行类型和方法定义的返回类型一致Object reVal = say.invoke(null, 300, "王五", '男');System.out.println("reVal 的运行类型=" + reVal.getClass());//String//在演示一个返回的案例Method m1 = bossCls.getDeclaredMethod("m1");Object reVal2 = m1.invoke(o);System.out.println("reVal2的运行类型=" + reVal2.getClass());//Monster} }class Monster {} class Boss {//类public int age;private static String name;public Boss() {//构造器}public Monster m1() {return new Monster();}private static String say(int n, String s, char c) {//静态方法return n + " " + s + " " + c;}public void hi(String s) {//普通public方法System.out.println("hi " + s);} }
-
练习
package com.hspedu.reflection.homework;import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method;/*** @author 韩顺平* @version 1.0*/ public class Homework01 {public static void main(String[] args) throws IllegalAccessException, InstantiationException, NoSuchFieldException, NoSuchMethodException, InvocationTargetException {/*** 定义PrivateTest类,有私有name属性,并且属性值为hellokitty* 提供getName的公有方法* 创建PrivateTest的类,利用Class类得到私有的name属性,修改私有的name属性值,并调用getName()的方法打印name属性值*///1. 得到 PrivateTest类对应的Class对象Class<PrivateTest> privateTestClass = PrivateTest.class;//2. 创建对象实例PrivateTest privateTestObj = privateTestClass.newInstance();//3. 得到name属性对象Field name = privateTestClass.getDeclaredField("name");//name属性是private//4. 暴破namename.setAccessible(true);name.set(privateTestObj, "天龙八部");//5. 得到getName方法对象Method getName = privateTestClass.getMethod("getName");//6. 因为getName() 是public,所有直接调用Object invoke = getName.invoke(privateTestObj);System.out.println("name属性值=" + invoke);//天龙八部} }class PrivateTest {private String name = "hellokitty";//默认无参构造器public String getName() {return name;} }
注意Class对象和创建实例化对象
-
package com.hspedu.reflection.homework;import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method;/*** @author 韩顺平* @version 1.0*/ public class Homework02 {public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {/*** 利用Class类的forName方法得到File类的class 对象* 在控制台打印File类的所有构造器* 通过newInstance的方法创建File对象,并创建E:\mynew.txt文件*///1. Class类的forName方法得到File类的class 对象Class<?> fileCls = Class.forName("java.io.File");//2. 得到所有的构造器Constructor<?>[] declaredConstructors = fileCls.getDeclaredConstructors();//遍历输出for (Constructor<?> declaredConstructor : declaredConstructors) {System.out.println("File构造器=" + declaredConstructor);}//3. 指定的得到 public java.io.File(java.lang.String)Constructor<?> declaredConstructor = fileCls.getDeclaredConstructor(String.class);String fileAllPath = "e:\\mynew.txt";Object file = declaredConstructor.newInstance(fileAllPath);//创建File对象//4. 得到createNewFile 的方法对象Method createNewFile = fileCls.getMethod("createNewFile");createNewFile.invoke(file);//创建文件,调用的是 createNewFile//file的运行类型就是FileSystem.out.println(file.getClass());System.out.println("创建文件成功" + fileAllPath);} }