Java的getDeclaredField和getField的使用和区别,以及如何获取父类的私有字段

Posted by 杨青波 on 2019-10-30

getDeclaredFields 和 getFields 的区别

  1. getDeclaredFields方法仅对类本身的字段有效果,对于继承的父类的字段无效
  2. getFields方法只能获取类及其父类的公共字段
  3. 获取父类的私有字段需要先使用getSuperClass获取父类Class,然后通过父类Class的getDeclaredFields方法获取父类的所有字段

示例演示

  1. 这是我们定义的一个父类,其中定义了一个公共字段 superDesc,和一个私有字段 superName
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class SuperModel {
private String superName;
public String superDesc;

public String getSuperDesc() {
return superDesc;
}
public void setSuperDesc(String superDesc) {
this.superDesc = superDesc;
}
public String getSuperName() {
return superName;
}
public void setSuperName(String superName) {
this.superName = superName;
}
}
  1. 这是我们定义的一个子类,其中也定义了一个公共字段modelDesc和一个私有字段modelName
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class SubModel extends SuperModel {
public String subDesc;
private String subName;

public String getSubDesc() {
return subDesc;
}
public void setSubDesc(String subDesc) {
this.subDesc = subDesc;
}
public String getSubName() {
return subName;
}
public void setSubName(String subName) {
this.subName = subName;
}
}
  1. 写了一些测试方法来测试 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
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
public class ReflectTest {

@Test
void getNameByGetFields() {
SubModel model = setup();
Class<? extends SuperModel> subClass = model.getClass();
try {
Field[] fields = subClass.getFields();
System.out.println("通过getFields方法遍历字段获取model字段: ");
for (Field field : fields) {
System.out.println(field.getName() + ":" + field.get(model));
}
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}

@Test
void getNameByDeclaredFields() {
SubModel model = setup();
Class<? extends SuperModel> subClass = model.getClass();
try {
System.out.println("通过getDeclaredFields方法获取model字段: ");
Field[] fields = subClass.getDeclaredFields();
for (Field field : fields) {
field.setAccessible(true);
System.out.println(field.getName() + ":" + field.get(model));
}
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}

@Test
void getNameBySuperClass() {
SubModel model = setup();
Class<? extends SuperModel> subClass = model.getClass();
try {
System.out.println("通过getSuperClass方法获取superName字段 ");
Class<?> superclass = subClass.getSuperclass();
Field[] fields = superclass.getDeclaredFields();
for (Field field : fields) {
field.setAccessible(true);
System.out.println(field.getName() + ":" + field.get(model));
}
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}

private SubModel setup() {
SubModel model = new SubModel();
model.setSuperDesc("父类公开字段");
model.setSuperName("父类私有字段");
model.setSubDesc("子类公开字段");
model.setSubName("子类私有字段");
return model;
}
}
  1. 当我使用getFields方法遍历所有字段时,输出了以下信息:

这说明getFields方法只能获取公共字段,但是可以同时获取本身和父类的公共字段
以下是JDK文档中的描述:

  1. 当我使用getDeclaredFields遍历所有字段时,输出了以下信息:

这说明getDeclaredFields方法只能获取类本身的字段,但是不能获取父类的字段。
以下时JDK文档中的描述:

  1. 当我使用getSuperClass获取父类Class后再使用父类的Class的getDeclaredFields方法,不出所料,输出的父类所有的字段。

写在最后

这说明要获取父类的私有字段必须先获取它的Class对象。而要遍历一个对象应该出现的所有字段,就需要遍历这个对象和这个对象的父类所有字段,不能一次性直接获取到所有字段。
最后给个分享个不错的JDK API在线文档地址,点过去进首页能发现惊喜哦。JDK8中文API在线文档



支付宝打赏 微信打赏

赞赏一下