2.2 在运行时查找字段
序列化一个对象,需要序列化其 字段值。
因此 serializeObject 方法首先要获取参数对象的 字段列表,可以通过参数对象的 class 对象实现。
class 对象提供了如下 Filed 相关方法:
| 方法签名 | 说明 |
|---|---|
| Field getField(String name) | 返回调用对象中名为 name 的 public 字段的 Field 对象 |
| Field getFields() | 返回所有 public 字段的 Field 数组 |
| Field getDeclaredField(String name) | 返回调用对象类、接口中声明的名为 name 的字段的 Field 对象 |
| Field getDeclaredFields() | 返回调用对象类、接口声明的所有字段的 Field 数组 |
getField():- 本类(接口)声明 + 继承
- 仅
public字段。
getDeclaredField- 本类声明
- 所有访问限定(
publicprotectedprivatepackage)
可能抛出的异常:
NoSuchFieldException:查询不存在的字段抛出。SecurityException:查询字段的功能可以在Java security manager中禁止,此时上述方法都会抛出。
需序列化对象,需要获取对象的所有字段,不管是自身声明的,还是继承自父类的,不管是 public 字段,还是 nonpublic 字段,上面四个方法无法实现该需求,需要自行实现:
Class<?> cls = obj.getClass();
List<Class> accum = new LinkedList<>();
while (cls != null) {
// 获取该层(本类)所有字段
Field[] fields = cls.getDeclaredFields();
for (Field f : fields) {
accum.add(f);
}
// 向上遍历
cls = cls.getSuperclass();
}
Field[] all = (Field[]) accm.toArray(new Field[accum.size()]);
关键点
- 通过
getSuperclass在继承树向上遍历。 - 在每一层中,通过
getDeclaredFields获取所有字段。
这样层层遍历,就能获取对象所有字段,包含自身声明和继承而来的,也包含所有的访问权限的。