先来写几个基本类:
1 2 3 4 5 6 7 8 * @author vincent */ @Data public class FatherClass { public String fatherName; public int fatherAge; }
1 2 3 4 5 6 7 8 9 10 11 12 13 * @author vincent */ @Data public class SonClass extends FatherClass { private String sonName; protected Integer sonAge; public String sonBirthday; public String show (String sonName, Integer sonAge, String sonBirthday) throws Exception { return sonName + "的年龄是:" + sonAge + ",生日是:" + sonBirthday; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 * @author vincent */ public class TestClass { private String MSG = "Original" ; public String getMSG () { return MSG; } private void privateMethod (String head, int tail) { System.out.println(head + tail); } }
getFields()
和 getDeclaredFields()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 * 通过反射获取类的所有变量 */ @Test public void fieldsTest () { Class sClass = SonClass.class; System.out.println("类的名称:" + sClass.getName()); System.out.println(); Field[] fields = sClass.getFields(); Arrays.stream(fields).forEach(System.out::println); System.out.println(); Field[] declaredFields = sClass.getDeclaredFields(); Arrays.stream(declaredFields).forEach(field -> { int modifier = field.getModifiers(); String modifiers = Modifier.toString(modifier); System.out.println(modifier + " -> " + modifiers); String typeName = field.getType().getName(); String fieldName = field.getName(); System.out.println(modifiers + " " + typeName + " " + fieldName); }); }
显示结果:
1 2 3 4 5 6 7 8 9 10 11 12 类的名称:com.example .reflect .SonClass public java.lang .String com.example .reflect .SonClass .sonBirthday public java.lang .String com.example .reflect .FatherClass .fatherName public int com.example .reflect .FatherClass .fatherAge 2 -> privateprivate java.lang .String sonName 4 -> protectedprotected java.lang .Integer sonAge 1 -> publicpublic java.lang .String sonBirthday
getMethods()
和 getDeclaredMethods()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 * 通过反射获取类的所有方法 */ @Test public void methodsTest () { Class sClass = SonClass.class; System.out.println("类的名字:" + sClass.getName()); System.out.println(); Method[] methods = sClass.getMethods(); Arrays.stream(methods).forEach(System.out::println); System.out.println(); Method[] declaredMethods = sClass.getDeclaredMethods(); Arrays.stream(declaredMethods).forEach(method -> { int modifiers = method.getModifiers(); String modifier = Modifier.toString(modifiers); System.out.print(modifier + " -> " + modifiers + "; " ); Class returnType = method.getReturnType(); System.out.print(modifier + " " + returnType.getName() + " " + method.getName() + "(" ); Parameter[] parameters = method.getParameters(); Arrays.stream(parameters).forEach(parameter -> { Class parameterType = parameter.getType(); System.out.print(parameterType.getName() + " " + parameter.getName() + " , " ); }); Class<?>[] exceptionTypes = method.getExceptionTypes(); if (exceptionTypes.length == 0 ) { System.out.println(");" ); } else { Arrays.stream(exceptionTypes).forEach(exceptionType -> { System.out.println(") throws " + exceptionType.getName() + ";" ); }); } }); }
显示结果:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 类的名字:com.example.reflect.SonClass public boolean com.example.reflect.SonClass.equals(java.lang.Object )public java.lang.String com.example.reflect.SonClass.toString()public int com.example.reflect.SonClass.hashCode()public java.lang.String com.example.reflect.SonClass.getSonName()public java.lang.String com.example.reflect.SonClass.show(java.lang.String ,java.lang.Integer,java.lang.String ) throws java.lang.Exceptionpublic java.lang.Integer com.example.reflect.SonClass.getSonAge()public java.lang.String com.example.reflect.SonClass.getSonBirthday()public void com.example.reflect.SonClass.setSonName(java.lang.String )public void com.example.reflect.SonClass.setSonAge(java.lang.Integer)public void com.example.reflect.SonClass.setSonBirthday(java.lang.String )public java.lang.String com.example.reflect.FatherClass.getFatherName()public int com.example.reflect.FatherClass.getFatherAge()public void com.example.reflect.FatherClass.setFatherName(java.lang.String )public void com.example.reflect.FatherClass.setFatherAge(int )public final void java.lang.Object .wait(long ,int ) throws java.lang.InterruptedExceptionpublic final native void java.lang.Object .wait(long ) throws java.lang.InterruptedExceptionpublic final void java.lang.Object .wait() throws java.lang.InterruptedExceptionpublic final native java.lang.Class java.lang.Object .getClass()public final native void java.lang.Object .notify()public final native void java.lang.Object .notifyAll()public -> 1 ; public boolean equals(java.lang.Object arg0 , );public -> 1 ; public java.lang.String toString();public -> 1 ; public int hashCode();public -> 1 ; public java.lang.String getSonName();protected -> 4 ; protected boolean canEqual(java.lang.Object arg0 , );public -> 1 ; public java.lang.String show(java.lang.String arg0 , java.lang.Integer arg1 , java.lang.String arg2 , ) throws java.lang.Exception;public -> 1 ; public java.lang.Integer getSonAge();public -> 1 ; public java.lang.String getSonBirthday();public -> 1 ; public void setSonName(java.lang.String arg0 , );public -> 1 ; public void setSonAge(java.lang.Integer arg0 , );public -> 1 ; public void setSonBirthday(java.lang.String arg0 , );
getFieldAccessor(obj).set(obj, value)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 * 访问私有变量并修改私有变量的值 */ @Test public void getAndModifyPrivateFiled () throws Exception { TestClass testClass = new TestClass(); Class<? extends TestClass> tClass = testClass.getClass(); Field privateField = tClass.getDeclaredField("MSG" ); if (Objects.nonNull(privateField)) { privateField.setAccessible(true ); System.out.println("Before Modify:MSG = " + testClass.getMSG()); * 调用 set(object , value) 修改变量的值,privateField 是获取到的私有变量,testClass 要操作的对象,"Modified" 为要修改成的值 */ privateField.set(testClass, "Modified" ); System.out.println("After Modify:MSG = " + testClass.getMSG()); } }
显示结果:
1 2 Before Modify :MSG = Original After Modify :MSG = Modified
Object invoke(Object obj, Object... args)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 * 访问对象的私有方法并赋值 */ @Test public void getPrivateMethod () throws Exception { TestClass testClass = new TestClass(); Class<? extends TestClass> tClass = testClass.getClass(); Method privateMethod = tClass.getDeclaredMethod("privateMethod" , String.class, int .class); if (Objects.nonNull(privateMethod)) { privateMethod.setAccessible(true ); * 使用 invoke 反射调用私有方法,privateMethod 是获取到的私有方法,testClass 要操作的对象,后面两个参数传实参 */ privateMethod.invoke(testClass, "Java Reflect" , 666 ); } }
显示结果:
对象中 String
类型属性为空的字段赋值为 null
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 public static <T> void stringEmptyToNull (T t) { Class<?> clazz = t.getClass(); Field[] fields = clazz.getDeclaredFields(); Arrays.stream(fields) .filter(f -> f.getType() == String.class) .filter(f -> { try { f.setAccessible(true ); String value = (String) f.get(t); return StringUtils.isEmpty(value); } catch (Exception ignore) { return false ; } }) .forEach(field -> { try { field.setAccessible(true ); field.set(t, null ); } catch (Exception ignore) { } }); }
比较同一类型,两个对象中不同的属性值
1 2 3 4 5 6 7 8 * @author vincent */ @Retention(RetentionPolicy.RUNTIME) public @interface TransferETC { String name () ; boolean required () default true ; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 * @author vincent */ public class ReflectExerciseDemo { @Data public static class PersonalInfoDto { @TransferETC(name = "姓名") private String name; @TransferETC(name = "年纪") private Integer age; @TransferETC(name = "性别") private String gender; @TransferETC(name = "住址") private String address; private String hobby; } @Data private static class Desc { private String fieldName; private String newOne; private String oldOne; } * 比较两个对象中不同的属性值 * * @param t1 * @param t2 * @param <T> * @return */ private <T> List<Desc> compareTo (T t1, T t2) { return Arrays.stream(t1.getClass().getDeclaredFields()) .filter(field -> { try { field.setAccessible(true ); return !Objects.equals(field.get(t1), field.get(t2)); } catch (IllegalAccessException e) { e.printStackTrace(); throw new RuntimeException(e); } }) .filter(item -> item.isAnnotationPresent(TransferETC.class)) .map(field -> { try { Desc desc = new Desc(); desc.setFieldName(field.getName()); desc.setNewOne(field.get(t1).toString()); desc.setOldOne(field.get(t2).toString()); TransferETC annotation = field.getAnnotation(TransferETC.class); Optional.ofNullable(annotation).map(TransferETC::name).filter(StringUtils::isNotEmpty).ifPresent(desc::setFieldName); return desc; } catch (IllegalAccessException e) { e.printStackTrace(); throw new RuntimeException(e); } }).collect(Collectors.toList()); } @Test public void t () { PersonalInfoDto infoDto = new PersonalInfoDto(); infoDto.setName("小囧" ); infoDto.setAge(20 ); infoDto.setGender("男" ); infoDto.setAddress("上海" ); infoDto.setHobby("篮球" ); PersonalInfoDto infoDto2 = new PersonalInfoDto(); infoDto2.setName("小乐" ); infoDto2.setAge(21 ); infoDto2.setGender("男" ); infoDto2.setAddress("北京" ); infoDto2.setHobby("足球" ); List<Desc> descs = compareTo(infoDto, infoDto2); System.out.println(JSON.toJSONString(descs, SerializerFeature.PrettyFormat)); } }
显示结果:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 [ { "fieldName":"姓名", "newOne":"小囧", "oldOne":"小乐" }, { "fieldName":"年纪", "newOne":"20", "oldOne":"21" }, { "fieldName":"住址", "newOne":"上海", "oldOne":"北京" } ]
把对象的属性名转化成中文展示
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 * @author vincent */ public class ReflectExerciseDemo { @Data public static class PersonalInfoDto { @TransferETC(name = "姓名") private String name; @TransferETC(name = "年纪") private Integer age; @TransferETC(name = "性别") private String gender; @TransferETC(name = "住址") private String address; private String hobby; } * 把对象的属性名转化成中文展示 * * @param t * @param <T> * @return */ private <T> String transferFields (T t) { return Arrays.stream(t.getClass().getDeclaredFields()) .filter(item -> item.isAnnotationPresent(TransferETC.class)) .map(field -> { try { field.setAccessible(true ); return String.format("%s:%s" , field.getAnnotation(TransferETC.class).name(), field.get(t)); } catch (IllegalAccessException e) { e.printStackTrace(); throw new RuntimeException(e); } }).collect(Collectors.joining(";" )); } @Test public void t2 () { PersonalInfoDto infoDto = new PersonalInfoDto(); infoDto.setName("小草" ); infoDto.setAge(18 ); infoDto.setGender("女" ); infoDto.setAddress("上海" ); infoDto.setHobby("跑步" ); String transferFields = transferFields(infoDto); System.out.println(transferFields); } }
显示结果:
案例源码:https://github.com/V-Vincen/reflect
If you like this blog or find it useful for you, you are welcome to comment on it. You are also welcome to share this blog, so that more people can participate in it. If the images used in the blog infringe your copyright, please contact the author to delete them. Thank you !