Java 日看一類(37)之IO包中的ObjectStreamField類

該類完成了Comparable<Object>接口

引入了

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類,屬於一種更高層次的單一功能性抽象。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章