java反射
java反射就是在JVM执行javac后,项目在运行状态中,能够动态的获取.class中的属性(private,protected,public)对应的字段名称,属性值。反射类中的方法。这种动态的获取类中的属性和方法称之为反射机制。
以下代码包含反射获取类中的任何对象属性。
/**
* @author BOBO
* @Title: bobo_base
* @Package com.bobo.base.reflected.dto
* @Description: 反射DTO
* @date 2018/3/13下午2:34
*/
@Data
@ApiModel("反射类DTO")
public class ReflectedDTO {
private Integer id;
private String name;
public String smallName;
protected String address;
ReflectedDTO(String name){
System.out.println("【protected】有Name参数的构造函数!name=" + name);
}
public ReflectedDTO(){
System.out.println("【public】无参数的构造函数");
}
public ReflectedDTO(Integer id,String smallName){
System.out.println("【public】有ID,smallName参数的构造函数!id=" + id + ",smallName=" + smallName);
}
private ReflectedDTO(Integer id){
System.out.println("【private】有ID的参数的构造函数! id=" + id);
}
//*****************************成员方法***********************************************************
public void show1(String s){
System.out.println("调用了:公有的,String参数的show1(): s = " + s);
}
protected void show2(){
System.out.println("调用了:受保护的,无参的show2()");
}
void show3(){
System.out.println("调用了:默认的,无参的show3()");
}
private String show4(int age){
System.out.println("调用了,私有的,并且有返回值的,int参数的show4(): age = " + age);
return "abcd";
}
}
/**
* @author BOBO
* @Title: bobo_base
* @Package com.bobo.reflected.reflectedImpl
* @Description: 反射Service
* @date 2018/3/12下午3:05
*/
@Service
public class ReflectedService {
/**
* * @Description: 反射获取方法(获取对象中的属性值)
* * @param list
* * @return
* * @author BOBO
* * @date 2018/3/11 下午9:52
*
*/
public <T> boolean reflectedMethod(T t) throws IntrospectionException, InvocationTargetException, IllegalAccessException {
Class<?> aClass = t.getClass();
//获取所有字段的Property
// PropertyDescriptor[] targetPds = BeanUtils.getPropertyDescriptors(aClass);
Field[] fields = aClass.getDeclaredFields();
for (Field field : fields) {
//获取当前字段的所有Property
PropertyDescriptor propertyDescriptor = new PropertyDescriptor(field.getName(), aClass);
//获取当前字段的getter方法
Method readMethod = propertyDescriptor.getReadMethod();
//如果getter的权限不为public,则修改accessible为true
if (!Modifier.isPublic(readMethod.getDeclaringClass().getModifiers())) {
readMethod.setAccessible(true);
}
//调用getter获得值,如果这个值为空则跳过
Object value = readMethod.invoke(t);
if (value == null) {
continue;
}
System.out.println(value.toString());
//如果当前字段类型为List
if (propertyDescriptor.getPropertyType().getName().equals(List.class.getName())) {
List<?> list = (List<?>) value;
list.forEach(dto -> {
System.err.println(dto.toString());
});
}
}
return true;
}
/**
* 通过Class对象可以获取某个类中的:构造方法、成员变量、成员方法;并访问成员;
*
* 1.获取构造方法:
* 1).批量的方法:
* public Constructor[] getConstructors():所有"公有的"构造方法
public Constructor[] getDeclaredConstructors():获取所有的构造方法(包括私有、受保护、默认、公有)
* 2).获取单个的方法,并调用:
* public Constructor getConstructor(Class... parameterTypes):获取单个的"公有的"构造方法:
* public Constructor getDeclaredConstructor(Class... parameterTypes):获取"某个构造方法"可以是私有的,或受保护、默认、公有;
*
* 调用构造方法:ß
* Constructor-->newInstance(Object... initargs)
*/
public void constructorsHandel(Class<?> classz) throws Exception {
//通过Class.forName获取类对象
Class classzz = Class.forName(classz.getName());
System.out.println("**********************所有公有构造方法*********************************");
//获取所有public标识的构造函数
Constructor[] constructors = classzz.getConstructors();
for (Constructor constructor : constructors) {
System.out.println(constructor);
}
System.out.println("************所有的构造方法(包括:私有、受保护、默认、公有)***************");
//获取所有构造函数
Constructor[] declaredConstructors = classzz.getDeclaredConstructors();
for (Constructor declaredConstructor : declaredConstructors) {
System.out.println(declaredConstructor);
}
System.out.println("*****************获取公有、空的构造方法*******************************");
Constructor constructor = classzz.getConstructor(null);
//1>、因为是无参的构造方法所以类型是一个null,不写也可以:这里需要的是一个参数的类型,切记是类型
//2>、返回的是描述这个无参构造函数的类对象
System.out.println(constructor);
//表示创建一个空的构造函数
constructor.newInstance();
System.out.println("******************获取公有构造方法,并调用*******************************");
//获取构造函数中参数为(Integer,String)对象实例
Constructor declaredConstructor = classzz.getDeclaredConstructor(Integer.class, String.class);
//newInstance能输出信息是因为此构造函数是public标识,
declaredConstructor.newInstance(123, "张三");
/**
* newInstance(Object... initargs)
使用此 Constructor 对象表示的构造方法来创建该构造方法的声明类的新实例,并用指定的初始化参数初始化该实例。
它的返回值是T类型,所以newInstance是创建了一个构造方法的声明类的新实例对象。并为之调用
*/
System.out.println("******************获取私有构造方法,并调用*******************************");
//如果为私有方法标识,需要如下设置。否则不能正常执行反射操作
//需要设置 privateConstructor.setAccessible(true);
Constructor privateConstructor = classzz.getDeclaredConstructor(Integer.class);
//暴力访问(忽略掉访问修饰符)
privateConstructor.setAccessible(true);
privateConstructor.newInstance(333);
}
/*
* 获取成员变量并调用:
*
* 1.批量的
* 1).Field[] getFields():获取所有的"公有字段"
* 2).Field[] getDeclaredFields():获取所有字段,包括:私有、受保护、默认、公有;
* 2.获取单个的:
* 1).public Field getField(String fieldName):获取某个"公有的"字段;
* 2).public Field getDeclaredField(String fieldName):获取某个字段(可以是私有的)
*
* 设置字段的值:
* Field --> public void set(Object obj,Object value):
* 参数说明:
* 1.obj:要设置的字段所在的对象;
* 2.value:要为字段设置的值;
*
*/
public <T> void filedHandle(T classz) throws Exception{
//通过getClass方式获取对象
Class<?> classzz = classz.getClass();
System.out.println("************获取所有公有的字段********************");
Field[] fields = classzz.getFields();
for (Field field : fields) {
System.out.println(field);
}
System.out.println("************获取所有的字段********************");
fields = classzz.getDeclaredFields();
for (Field field : fields) {
System.out.println(field);
}
System.out.println("*************获取字段**并调用【1】***********************************");
fields = classzz.getDeclaredFields();
for (Field field : fields) {
//获取当前字段的所有Property
PropertyDescriptor propertyDescriptor = new PropertyDescriptor(field.getName(), classzz);
//获取当前字段的读属性 (getXXX)
Method readMethod = propertyDescriptor.getReadMethod();
//将当前字段设置为公有属性
field.setAccessible(true);
//通过Method获取属性值
Object value = readMethod.invoke(classz);
System.out.println(value);
}
//重定向值
for (Field field : fields) {
//获取当前字段的所有Property
PropertyDescriptor propertyDescriptor = new PropertyDescriptor(field.getName(), classzz);
//获取当前字段的写属性 (setXXX)
Method writeMethod = propertyDescriptor.getWriteMethod();
//获取名称
String name = writeMethod.getName();
//如果是smallName 重定向值 【公有字段】
if(name.equals("setSmallName")){
//获取setXXX 重新赋值
writeMethod.invoke(classz,"11");
}
//【私有字段】 需要添加setAccessible(true);
if(name.equals("setName")){
//将当前字段设置为公有属性
field.setAccessible(true);
//获取setXXX 重新赋值
writeMethod.invoke(classz,"重定向名称");
}
}
System.out.println("*************获取字段**并调用【2】***********************************");
//获取已知字段
Field id = classzz.getDeclaredField("id");
//获取单独的字段值
// id.setAccessible(true);
// System.out.println(id.get(classz));
//获取对象 类似 ReflectedDTO o = new ReflectedDTO();
//这样newInstance()代表创建一个无参的构造函数,也可以在newInstance()括弧中添加参数
Object o = classzz.getConstructor().newInstance();
//解除私有限定
id.setAccessible(true);
id.set(o,999);
//强转类型 (此处强转是为了输出)
ReflectedDTO reflectedDTO = (ReflectedDTO)o;
System.out.println("第二种方式重置字段ID值为:" + reflectedDTO.getId());
}
/*
* 获取成员变量并调用:
*
* 1.批量的
* 1).Field[] getFields():获取所有的"公有字段"
* 2).Field[] getDeclaredFields():获取所有字段,包括:私有、受保护、默认、公有;
* 2.获取单个的:
* 1).public Field getField(String fieldName):获取某个"公有的"字段;
* 2).public Field getDeclaredField(String fieldName):获取某个字段(可以是私有的)
*
* 设置字段的值:
* Field --> public void set(Object obj,Object value):
* 参数说明:
* 1.obj:要设置的字段所在的对象;
* 2.value:要为字段设置的值;
*
*/
public void methodHandel(Class<?> classz) throws Exception{
Class<?> aClass = Class.forName(classz.getName());
System.out.println("***************获取所有的”公有“方法*******************");
Method[] methods = aClass.getMethods();
for (Method method : methods) {
System.out.println(method);
}
System.out.println("***************获取所有的”私有“方法*******************");
Method[] declaredMethods = aClass.getDeclaredMethods();
for (Method declaredMethod : declaredMethods) {
System.out.println(declaredMethod);
}
System.out.println("***************获取私有的show4()方法******************");
Method method = aClass.getDeclaredMethod("show4", int.class);
method.setAccessible(true);
Object o = aClass.getConstructor().newInstance();
method.invoke(o,567);
}
}
/**
* @Description: 反射应用
* @param
* @return
* @author BOBO
* @date 2018/3/12 下午3:11
*/
private void reflectedMethod() throws Exception {
// List<Data1> list = new ArrayList<>();
// Data1 data1 = new Data1();
// data1.setGetInfo2("23232");
// data1.setId(23);
// data1.setInfo1("44444");
// list.add(data1);
//
// GenericDTO genericDTO = new GenericDTO();
// genericDTO.setClassName("老哈迪斯");
// genericDTO.setClassPath("path");
// genericDTO.setId(345);
// genericDTO.setClassType("classType领导来了");
// genericDTO.setClassInfo(list);
//
// reflectedService.reflectedMethod(genericDTO);
//获取构造函数的反射对象方法
// reflectedService.constructorsHandel(ReflectedDTO.class);
// ReflectedDTO reflectedDTO = new ReflectedDTO();
// reflectedDTO.setId(222);
// reflectedDTO.setAddress("张家口");
// reflectedDTO.setName("李四");
// reflectedDTO.setSmallName("小四");
//
// //获取队形属性方法
// reflectedService.filedHandle(reflectedDTO);
reflectedService.methodHandel(ReflectedDTO.class);
}