解析
1.获取反射对象类信息
object.getClass()
:获取类对象信息
Animal animal = new Animal();
animal.setCode("10");
animal.setName("miao");
Class<?> aClass = animal.getClass();
System.out.println(aClass);
//class com.example.demo.pojo.relfect.Animal
aClass.getName()
:获取类全名,包名+类名
System.out.println(aClass.getName());
// com.example.demo.pojo.relfect.Animal
aClass.getSimpleName()
:仅获取类名
System.out.println(aClass.getSimpleName());
// Animal
aClass.getClassLoader()
:获取该类的加载器
System.out.println(aClass.getClassLoader());
// sun.misc.Launcher$AppClassLoader@18b4aac2
拓展一下类加载器(双亲委派):
类的加载是从自定义类中,委托到最上层加载器开始寻找对应的类,找不到才逐个往下找。
若有上下层重复,会报错。也就是说沙箱保护机制会优先选择上层有的类。
2.获取类中的字段、方法
注意事项: 若要获取到值或调用的是private修饰的,需要先走第三步,让私有失效。
aClass.getDeclaredFields()
:获取该类所有的字段
aClass.getDeclaredField("字段名")
:获取该类某个字段
Field[] fields = aClass.getDeclaredFields();
Field code = aClass.getDeclaredField("code");
for (Field field : fields) {
System.out.println(field.getName());
System.out.println(field.get(animal)+"\n");
/**
* code
* 10
*
* codeBz
* null
*
* name
* miao
*
* nameBz
* null
*/
}
aClass.getMethods()
:获取该类所有方法
aClass.getMethod("方法名", 方法类型.class)
:获取对应某个方法
Method[] methods = aClass.getMethods();
Method method1 = aClass.getMethod("methodTest", String.class);
for (Method method : methods) {
if (method.getName().equals("methodTest")) {
System.out.println(method.getName());
// methodTest
System.out.println(method.invoke(animal, "加菲猫"));
// 加菲猫
}
/**
* equals
* toString
* hashCode
* getName
* setName
* setCode
* getNameBz
* setCodeBz
* setNameBz
* getCodeBz
* getCode
* wait
* wait
* wait
* getClass
* notify
* notifyAll
*/
}
3.设置私有字符失效->private
方法.setAccessible(true)
/字段.setAccessible(true)
.
@ApiModelProperty("原动物代码")
private String code;
Field code = aClass.getDeclaredField("code");
// code.setAccessible(true);
code.get(animal);
若不先让私有化失效,操作过程中可能会出现报错。
放开code.setAccessible(true);
就好了。
Exception in thread "main" java.lang.IllegalAccessException: Class com.example.demo.pojo.relfect.Reflector can not access a member of class com.example.demo.pojo.relfect.Animal with modifiers "private"
at sun.reflect.Reflection.ensureMemberAccess(Reflection.java:102)
at java.lang.reflect.AccessibleObject.slowCheckMemberAccess(AccessibleObject.java:296)
at java.lang.reflect.AccessibleObject.checkAccess(AccessibleObject.java:288)
at java.lang.reflect.Field.get(Field.java:390)
4.获取某个对象对应字段的值
字段.get(对象)
:表示获取某个对象中该字段的值。注意私有情况要先设定失效。
Animal animal = new Animal();
animal.setCode("10");
animal.setName("miao");
Class<?> aClass = animal.getClass();
Field code = aClass.getDeclaredField("code");
code.setAccessible(true);
code.get(animal);
方法.invoke(方法名,入参)
:调用某个方法
// 获取某个方法对象
Method method1 = aClass.getMethod("methodTest", String.class);
// 私有化失效
method1.setAccessible(true);
// 调用animal对象中的methodTest方法
method1.invoke(animal,"加菲猫");
5.设置某个字段的值
字段.set(对象,要设置的值)
:设置某个字段的值。注意私有情况要先设定失效。
Field code = aClass.getDeclaredField("code");
code.setAccessible(true);
//设置animal对象中code的值
code.set(animal,"反射设置的code");
小案例
映射实体类
package com.example.demo.pojo.relfect;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
public class Animal {
@ApiModelProperty("原动物代码")
String code;
@ApiModelProperty("原动物名")
String codeBz;
@ApiModelProperty("标准动物代码")
String name;
@ApiModelProperty("标准动物名")
String nameBz;
public String methodTest(String arg){
return arg;
}
}
具体实现类
其中的枚举类:AnimalEnum
package com.example.demo.pojo.relfect;
import com.example.demo.pojo.AnimalEnum;
import java.lang.reflect.Field;
public class Reflector {
public static void main(String[] args) {
//现在要通过code进行标准化name。
Animal animal = new Animal();
animal.setCode("10");
animal.setName("miao");
reflectCodeName(animal, "code", "name", AnimalEnum.match(animal.getCode()), "codeBz", "nameBz");
System.out.println(animal);
// Animal(code=10, codeBz=10, name=miao, nameBz=cat)
}
private static void reflectCodeName (Object object, String sourceField, String sourceField2, AnimalEnum
animalEnum, String targetSource, String targetSource2){
try {
// 原数据判断
Class<?> aClass = object.getClass();
Field originValue = aClass.getDeclaredField(sourceField);
originValue.setAccessible(true);
Object o = originValue.get(object);
if (o == null) {
return;
}
if (animalEnum == null) {
return;
}
// 获取标准数据
Field targetValue = aClass.getDeclaredField(targetSource);
// 设置private字段失效
targetValue.setAccessible(true);
//放入标准属性
targetValue.set(object, animalEnum.getCode());
Field originValue2 = aClass.getDeclaredField(sourceField2);
originValue2.setAccessible(true);
Object o2 = originValue2.get(object);
if (o == null) {
return;
}
// 获取标准数据
Field targetValue2 = aClass.getDeclaredField(targetSource2);
targetValue2.setAccessible(true);
targetValue2.set(object, animalEnum.getType());
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
}
6.当需要反射到父类时
子类:
public class Cat extends Animal{
@ApiModelProperty("猫叫")
String miao;
@ApiModelProperty("鱼品种")
String fish;
}
实现类:
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class ReflectorDad {
public static void main(String[] args) {
Cat cat = new Cat();
// 获取当前类字段
Class<?> aClass = cat.getClass();
Field[] fields = aClass.getDeclaredFields();
for (Field field : fields) {
System.out.println(field.getName());
/**
* miao
* fish
*/
}
// 获取父类字段
Class<?> superclass = aClass.getSuperclass();
Field[] superFields = superclass.getDeclaredFields();
for (Field superField : superFields) {
System.out.println(superField.getName());
/**
* code
* codeBz
* name
* nameBz
*/
}
// 获取该类所有有关的字段
List<Field> allField = getAllField(cat);
for (Field field : allField) {
System.out.println(field.getName());
}
}
/**
* 获取所有的字段信息
* @param o
* @return
*/
public static List<Field> getAllField(Object o){
List<Field> fields = new ArrayList<>();
Class<?> aClass = o.getClass();
while (aClass!=null){
Field[] declaredFields = aClass.getDeclaredFields();
for (Field declaredField : declaredFields) {
System.out.println(declaredField.getName());
}
fields.addAll(Arrays.asList(declaredFields));
if (aClass.getSuperclass()!=null){
System.out.println(aClass.getSuperclass());
aClass=aClass.getSuperclass();
}else {
aClass = null;
}
}
return fields;
}
}
7.反射案例箱
/**
* 筛选转换
* 1.挑选出指定类型的数据
* 2.转换成指定类型的对象
*
* @param source 数据
* @param category 指定类型
* @param tClass 指定类的类型
* @param field 指定属性
* @param <T>
* @return
*/
private static <T> List<T> filterTransformation(List<?> source, String category, Class<?> tClass, String field) {
List<?> objects = source.stream().filter(s -> {
try {
return s.getClass().getSuperclass().getDeclaredField(field).get(s).
equals(category);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
return false;
}).collect(Collectors.toList());
return (List<T>) BeanUtil.copyList(objects, tClass);
}