定义

代表可被序列化的字段。即指定哪些字段将参与序列化,并封装这些参与序列化的字段信息。所有可被序列化的字段需要封装为一个ObjectStreamField数组,且数组变量名必须为serialPersistentFields。

  1. public class ObjectStreamField implements Comparable<Object> {
  2. ...
  3. }
  • 实现 Comparable 接口,可比较大小

重写两个方法toString和compareTo

  1. @Override
  2. public int compareTo(Object obj) {
  3. // 强转为ObjectStreamField
  4. ObjectStreamField other = (ObjectStreamField) obj;
  5. // 当前字段是否为基本类型
  6. boolean isPrim = isPrimitive();
  7. // 两个字段类型不相同的场合
  8. if(isPrim != other.isPrimitive()) {
  9. // 基本类型倒序,非基本类型正序
  10. return isPrim ? -1 : 1;
  11. }
  12. // 调用string的比较方法
  13. return name.compareTo(other.name);
  14. }
  15. /**
  16. * Return a string that describes this field.
  17. */
  18. @Override
  19. public String toString() {
  20. // 返回字段签名和字段名称
  21. return getSignature() + ' ' + name;
  22. }

成员变量

  1. // 字段名称
  2. private final String name;
  3. // 封装的字段(可能为null)
  4. private final Field field;
  5. // 字段类型
  6. private final Class<?> type;
  7. // 字段类型的JVM规范签名
  8. private final String signature;
  9. // JVM规范签名(懒加载生成)
  10. private String typeSignature;
  11. // 字段是否非共享(共享字段会共用一段序列化信息)
  12. private final boolean unshared;
  13. // 当前字段在所有待序列化字段中的偏移量(以字节为偏移单位)
  14. private int offset;

构造函数

构造函数(传入字段名和字段数据类型,默认可共享)

  1. // 构造函数(传入字段名和字段数据类型,默认可共享)
  2. public ObjectStreamField(String name, Class<?> type) {
  3. this(name, type, false);
  4. }
  5. // 构造函数(传入数据名、数据类型、共享权限)
  6. public ObjectStreamField(String name, Class<?> type, boolean unshared) {
  7. if(name == null) {
  8. throw new NullPointerException();
  9. }
  10. this.name = name;
  11. this.type = type;
  12. this.unshared = unshared;
  13. // 字段、签名初始化
  14. this.field = null;
  15. this.signature = null;
  16. }

构造函数(传入数据名、签名、共享权限)

  1. // 构造函数(传入数据名、签名、共享权限)
  2. ObjectStreamField(String name, String signature, boolean unshared) {
  3. if(name == null) {
  4. throw new NullPointerException();
  5. }
  6. this.name = name;
  7. // 返回字符串的规范形式
  8. this.signature = signature.intern();
  9. this.unshared = unshared;
  10. this.field = null;
  11. // 根据类型签名获得数据类型
  12. switch(signature.charAt(0)) {
  13. case 'Z':
  14. type = Boolean.TYPE;
  15. break;
  16. case 'B':
  17. type = Byte.TYPE;
  18. break;
  19. case 'C':
  20. type = Character.TYPE;
  21. break;
  22. case 'S':
  23. type = Short.TYPE;
  24. break;
  25. case 'I':
  26. type = Integer.TYPE;
  27. break;
  28. case 'J':
  29. type = Long.TYPE;
  30. break;
  31. case 'F':
  32. type = Float.TYPE;
  33. break;
  34. case 'D':
  35. type = Double.TYPE;
  36. break;
  37. case 'L':
  38. case '[':
  39. type = Object.class;
  40. break;
  41. default:
  42. throw new IllegalArgumentException("illegal signature");
  43. }
  44. }

构造函数(给予映射的字段,是否共享控制,是否显示实际类型))

  1. ObjectStreamField(Field field, boolean unshared, boolean showType) {
  2. this.field = field;
  3. this.unshared = unshared;
  4. name = field.getName();
  5. // 获取字段类型
  6. Class<?> ftype = field.getType();
  7. // 显示类型为true的场合,返回字段类型,否则返回Object类型
  8. type = (showType || ftype.isPrimitive()) ? ftype : Object.class;
  9. // 获取类型对应的签名
  10. signature = getClassSignature(ftype).intern();
  11. }

内部方法

getField()方法

  1. // 获取允许反序列化的字段
  2. Field getField() {
  3. return field;
  4. }

getName()方法

  1. // 返回字段的名称
  2. public String getName() {
  3. return name;
  4. }

getType()方法

  1. // 返回字段的类型
  2. @CallerSensitive
  3. public Class<?> getType() {
  4. // 获得控制台安全管理器
  5. if(System.getSecurityManager() != null) {
  6. // 获得调用映像
  7. Class<?> caller = Reflection.getCallerClass();
  8. // 判定两个类型的ClassLoader是否相等或者为祖先关系(caller为type的祖先)
  9. if(ReflectUtil.needsPackageAccessCheck(caller.getClassLoader(), type.getClassLoader())) {
  10. // 如果该类型调用不可访问的包则抛出SecurityException
  11. ReflectUtil.checkPackageAccess(type);
  12. }
  13. }
  14. return type;
  15. }

image.png

getSignature()方法

  1. // 返回字段签名
  2. String getSignature() {
  3. if(signature != null) {
  4. return signature;
  5. }
  6. String sig = typeSignature;
  7. // This lazy calculation is safe since signature can be null iff one
  8. // of the public constructors are used, in which case type is always
  9. // initialized to the exact type we want the signature to represent.
  10. if(sig == null) {
  11. // 获取类型对应的签名
  12. typeSignature = sig = getClassSignature(type).intern();
  13. }
  14. return sig;
  15. }
  16. // 获取类型对应的签名
  17. static String getClassSignature(Class<?> cl) {
  18. // 基本类型的场合
  19. if(cl.isPrimitive()) {
  20. return getPrimitiveSignature(cl);
  21. } else {
  22. // 非基本类型的场合
  23. return appendClassSignature(new StringBuilder(), cl).toString();
  24. }
  25. }
  26. // 拼接类型签名
  27. static StringBuilder appendClassSignature(StringBuilder sbuf, Class<?> cl) {
  28. // 获取数组类型
  29. while(cl.isArray()) {
  30. sbuf.append('[');
  31. cl = cl.getComponentType();
  32. }
  33. // 基本类型
  34. if(cl.isPrimitive()) {
  35. sbuf.append(getPrimitiveSignature(cl));
  36. } else {
  37. // 对象类型
  38. sbuf.append('L').append(cl.getName().replace('.', '/')).append(';');
  39. }
  40. return sbuf;
  41. }
  42. // 基本类型的签名
  43. private static String getPrimitiveSignature(Class<?> cl) {
  44. if(cl == Integer.TYPE) {
  45. return "I";
  46. } else if(cl == Byte.TYPE) {
  47. return "B";
  48. } else if(cl == Long.TYPE) {
  49. return "J";
  50. } else if(cl == Float.TYPE) {
  51. return "F";
  52. } else if(cl == Double.TYPE) {
  53. return "D";
  54. } else if(cl == Short.TYPE) {
  55. return "S";
  56. } else if(cl == Character.TYPE) {
  57. return "C";
  58. } else if(cl == Boolean.TYPE) {
  59. return "Z";
  60. } else if(cl == Void.TYPE) {
  61. return "V";
  62. } else {
  63. throw new InternalError();
  64. }
  65. }

getTypeCode()方法

  1. // 返回字段签名
  2. public char getTypeCode() {
  3. return getSignature().charAt(0);
  4. }

getTypeString()方法

  1. // 返回字段签名,对于基本类型,返回null
  2. public String getTypeString() {
  3. return isPrimitive() ? null : getSignature();
  4. }

getOffset()方法

  1. // 返回字段的偏移量
  2. public int getOffset() {
  3. return offset;
  4. }

setOffset()方法

  1. // 设置字段的偏移量
  2. protected void setOffset(int offset) {
  3. this.offset = offset;
  4. }

isPrimitive()方法

  1. // 当前字段是否为基本类型
  2. public boolean isPrimitive() {
  3. // 返回字段签名
  4. char tcode = getTypeCode();
  5. return ((tcode != 'L') && (tcode != '['));
  6. }

isUnshared()方法

  1. // 判断当前字段是否非共享
  2. public boolean isUnshared() {
  3. return unshared;
  4. }