Java反射获取对象成员属性,getFields()与getDeclaredFields()方法的区别
·
在工作中遇到一个问题,就是你需要去判断某个字符串是不是对象的某个成员属性名,然后根据判断结果去操作这个成员属性。想了下之后,我们可以根据Java反射中的getDeclaredFields()或者getFields()方法来实现我们的需求。
首先说明一下getDeclaredFields()和getFields()这两个方法的区别:
getFields(): 获取某个类的所有的public字段,其中是包括父类的public字段的。
getDeclaredFields():获取某个类的自身的所有字段,不包括父类的字段。
我们创建一个父类:Person , 其中name属性特意声明成了public类型
public class Person {
public String name;
private int age;
// 省略get、set方法
}
创建子类:Student,其中studentNumber属性也声明为public
public class Student extends Person {
public String studentNumber;
private double grade;
// 省略get、set方法
}
首先测试一下 getFields()方法:
public static void main(String[] args) throws IllegalAccessException {
Student student = new Student();
student.setGrade(99);
student.setStudentNumber("20191223");
student.setName("zhangsan");
student.setAge(22);
Field[] fields = student.getClass().getFields();
for(Field field : fields){
System.out.println("成员属性:"+field.getName()+" 成员属性修饰符: "+field.getModifiers()+" 成员属性值: "+field.get(student));
}
// 成员属性:studentNumber 成员属性修饰符: 1 成员属性值: 20191223
// 成员属性:name 成员属性修饰符: 1 成员属性值: zhangsan
}
从代码可以看到,我们使用的是getFields()方法,结果中也可以看出,fields数组中只包含了public修饰的成员属性,其中除了子类本身的public类型属性,也包括了父类的public类型属性。
额,上面的成员属性修饰符返回的是int型变量,1代表的就是public,2代表的就是private,具体的对照关系可以参看java.lang.reflect.Modifier 这个类。
在测试一下 getDeclaredField()方法:
public static void main(String[] args) throws IllegalAccessException {
Student student = new Student();
student.setGrade(99);
student.setStudentNumber("20191223");
student.setName("zhangsan");
student.setAge(22);
Field[] fields = student.getClass().getDeclaredFields();
for(Field field : fields){
System.out.println("成员属性:"+field.getName()+" 成员属性修饰符: "+field.getModifiers()+" 成员属性值: "+field.get(student));
}
}
这样直接输出的结果:
Exception in thread "main" java.lang.IllegalAccessException: Class com.baiding.test.InvokeTest can not access a member of class com.baiding.model.Student with modifiers "private"
对于私有的成员变量来说,要操作其属性值的话,就需要设置setAccessible(true);
field.setAccessible(true)就是让我们在反射时可以操作私有成员属性的值。
修改后的代码如下:
public static void main(String[] args) throws IllegalAccessException {
Student student = new Student();
student.setGrade(99);
student.setStudentNumber("20191223");
student.setName("zhangsan");
student.setAge(22);
Field[] fields = student.getClass().getDeclaredFields();
for(Field field : fields){
// 获取原来的访问控制权限
boolean accessFlag = field.isAccessible();
if(!field.isAccessible()) field.setAccessible(true);
System.out.println("成员属性:"+field.getName()+" 成员属性修饰符: "+field.getModifiers()+" 成员属性值: "+field.get(student));
field.setAccessible(accessFlag);
}
// 成员属性:studentNumber 成员属性修饰符: 1 成员属性值: 20191223
// 成员属性:grade 成员属性修饰符: 2 成员属性值: 99.0
}
对于上述代码,增加了判断: if(!field.isAccessible()) field.setAccessible(true);
修改了字段的访问控制权限毕竟是不安全的,所以在操作结束后有必要修改回原来的访问控制权限。
从结果也可以看出:fields数组中只包含了子类Student的成员属性,不包含父类任何类型的成员属性
更多推荐
已为社区贡献1条内容
所有评论(0)