Java 日看一类(37)之IO包中的ObjectStreamField类
阅读原文时间:2021年04月20日阅读:1

该类完成了Comparable接口

引入了

import java.lang.reflect.Field; import sun.reflect.CallerSensitive; import sun.reflect.Reflection; import sun.reflect.misc.ReflectUtil;

该类的类头注释如下:

/** * A description of a Serializable field from a Serializable class. An array * of ObjectStreamFields is used to declare the Serializable fields of a class. * * @author Mike Warres * @author Roger Riggs * @see ObjectStreamClass * @since 1.2 */

大意如下:

该类是描述串行化类中串行化字段的类

一般会用一个ObjectStreamField数组来声明一个类中的串行化字段

该类含有如下的成员变量:

字段名称

private final String name;

字段数据类型的JVM签字(基础数据类型标识)

private final String signature;

字段数据类型

private final Class type;

是否将序列化字段值设置为非共享

private final boolean unshared;

字段相应的映射(如果存在才会被赋值)

private final Field field;

封闭字段偏移量

private int offset = 0;

该类含有如下的成员方法:

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

public ObjectStreamField(String name, Class type) {
this(name, type, false); }

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

public ObjectStreamField(String name, Class type, boolean unshared) { if (name == null) { throw new NullPointerException();
} this.name = name;
this.type = type;
this.unshared = unshared;
signature = getClassSignature(type).intern();//获得传入数据类型的JVM签名 field = null; }

构造函数(default类型的,传入的是签名而不是类型)

ObjectStreamField(String name, String signature, boolean unshared) { if (name == null) { throw new NullPointerException();
} this.name = name;
this.signature = signature.intern();//返回字符串的规范形式 this.unshared = unshared;
field = null; switch (signature.charAt(0)) {//根据类型签名获得数据类型 case 'Z': type = Boolean.TYPE; break;
case 'B': type = Byte.TYPE; break;
case 'C': type = Character.TYPE; break;
case 'S': type = Short.TYPE; break;
case 'I': type = Integer.TYPE; break;
case 'J': type = Long.TYPE; break;
case 'F': type = Float.TYPE; break;
case 'D': type = Double.TYPE; break;
case 'L': case '[': type = Object.class; break;
default: throw new IllegalArgumentException("illegal signature");
}
}

构造函数(给予映射的字段,是否共享控制,对getType()方法返回值的控制(返回实际类型或基础类型,或者是class类))

ObjectStreamField(Field field, boolean unshared, boolean showType) { this.field = field;//绑定映射字段 this.unshared = unshared;
name = field.getName();//获得字段名称 Class ftype = field.getType();//字段类型 type = (showType || ftype.isPrimitive()) ? ftype : Object.class;//如果该类的展示类型为真或者字段类型为基础类型则将字段类型绑定到type 上,否则绑定Object.class signature = getClassSignature(ftype).intern();//获得该类的签名 }

获得字段名称

public String getName() {
return name; }

获得字段类型

@CallerSensitive public Class getType() {
if (System.getSecurityManager() != null) {//获得控制台安全管理器 Class caller = Reflection.getCallerClass();//获得调用映像,native函数,看不到默认的调用类型 if (ReflectUtil.needsPackageAccessCheck(caller.getClassLoader(), type.getClassLoader())) {//判定两个类型的ClassLoader是否相等或者为祖先关系(caller为type的祖先) ReflectUtil.checkPackageAccess(type);//如果该类型调用不可访问的包则抛出SecurityException }
} return type; }

获得类型标识符

public char getTypeCode() { return signature.charAt(0);//签名中的第一位字符就可以分辨签名类型,所以返回一个即可 }

获得类型的字符串

public String getTypeString() { return isPrimitive() ? null : signature;//如果是基础类型就不返回,非基础类型返回类型签名 }

返回字段偏移量

public int getOffset() {
return offset; }

设置字段偏移量

protected void setOffset(int offset) {
this.offset = offset; }

判定类型是否为基础类型

public boolean isPrimitive() { char tcode = signature.charAt(0);
return ((tcode != 'L') && (tcode != '['));//对应关系可见上面的构造函数,或见下面的签字获取函数 }

返回是否不可共享

public boolean isUnshared() {
return unshared; }

字段名称比较

public int compareTo(Object obj) {
ObjectStreamField other = (ObjectStreamField) obj;//获得传入对象的流字段 boolean isPrim = isPrimitive();
if (isPrim != other.isPrimitive()) {//如果两个不全为基础类型或非基础类型 return isPrim ? -1 : 1;//如果当前值为基础类型则返回-1(对应传入值为非基础),非基础类型则返回1(对应传入值为基础) } return name.compareTo(other.name);//两个类型全为基础或非基础,按照字典序比较两个字段的名字 }

返回标准的字段描述

public String toString() {
return signature + ' ' + name; }

返回该字段的字段类型映射(可能为空,如果没有绑定映射的话)

Field getField() {
return field; }

返回类型签字

String getSignature() {
return signature; }

获得字段签字

private static String getClassSignature(Class cl) {
StringBuilder sbuf = new StringBuilder();//类似StingBuffer,可以理解为阉割版的,执行效率比StringBuffer高 while (cl.isArray()) {//判定传入是否是个数组 sbuf.append('[');//如果是就写入[ cl = cl.getComponentType();//返回该数组的类型 } if (cl.isPrimitive()) {//如果是基础类型 if (cl == Integer.TYPE) {
sbuf.append('I');
} else if (cl == Byte.TYPE) {
sbuf.append('B');
} else if (cl == Long.TYPE) {
sbuf.append('J');
} else if (cl == Float.TYPE) {
sbuf.append('F');
} else if (cl == Double.TYPE) {
sbuf.append('D');
} else if (cl == Short.TYPE) {
sbuf.append('S');
} else if (cl == Character.TYPE) {
sbuf.append('C');
} else if (cl == Boolean.TYPE) {
sbuf.append('Z');
} else if (cl == Void.TYPE) {
sbuf.append('V');
} else { throw new InternalError();//内部错误,一般是被其他线程修改了 }
} else {//非基础类型,添加如下数据 sbuf.append('L' + cl.getName().replace('.', '/') + ';');
} return sbuf.toString();//返回标准化后的类型签字 }

该类属于‘常用类’(在封装好的Object操作类中大量使用该类),该类实质上是类字段的一种抽象化表现,但同时也和Field类有所不同,由于该类单纯针对串行化字段,所以提供的功能和属性少于Field类,属于一种更高层次的单一功能性抽象。