ZetCode

Java ObjectStreamField 类

最后修改时间:2025 年 4 月 16 日

java.io.ObjectStreamField 类描述了一个类的可序列化字段。它用于自定义序列化,以指定字段名称和类型。此类有助于控制对象的序列化形式。

ObjectStreamField 主要与 ObjectStreamClass 一起使用,以定义可序列化字段。它提供有关字段名称、类型以及它们是基本类型还是对象引用的信息。这使得可以精确控制序列化。

ObjectStreamField 类概述

ObjectStreamField 表示一个可序列化字段,包含其名称和类型。该类提供了检查字段特性的方法。在实现 serialPersistentFields 用于自定义序列化时使用。

public class ObjectStreamField implements Comparable<Object> {
    public ObjectStreamField(String name, Class<?> type);
    public ObjectStreamField(String name, Class<?> type, boolean unshared);
    public String getName();
    public Class<?> getType();
    public char getTypeCode();
    public String getTypeString();
    public int getOffset();
    public boolean isPrimitive();
    public boolean isUnshared();
    public int compareTo(Object obj);
    public String toString();
}

以上代码显示了 ObjectStreamField 的关键方法。这些方法允许在序列化期间检查字段属性。该类实现了 Comparable 用于在序列化形式中对字段进行排序。

创建 ObjectStreamField 实例

创建 ObjectStreamField 实例以描述可序列化字段。构造函数接受字段名称和类型参数。一个可选的 unshared 标志控制序列化期间的引用共享。

Main.java
import java.io.ObjectStreamField;

public class Main {

    public static void main(String[] args) {
        // Create fields for different types
        ObjectStreamField intField = new ObjectStreamField("age", int.class);
        ObjectStreamField stringField = new ObjectStreamField("name", String.class);
        ObjectStreamField customField = new ObjectStreamField("data", byte[].class, true);
        
        System.out.println("Created fields:");
        System.out.println(intField);
        System.out.println(stringField);
        System.out.println(customField);
        
        // Verify field properties
        System.out.println("\nField types:");
        System.out.println("age is primitive: " + intField.isPrimitive());
        System.out.println("name is unshared: " + stringField.isUnshared());
        System.out.println("data type code: " + customField.getTypeCode());
    }
}

此示例演示了创建不同的 ObjectStreamField 实例。前两个字段是标准的,而第三个被标记为 unshared。输出显示了字段属性,包括类型代码和基本状态。

在序列化中使用 ObjectStreamField

ObjectStreamField 通常用于 serialPersistentFields 声明中。此静态数组定义了哪些字段被序列化及其顺序。它提供了对序列化形式的控制。

Person.java
import java.io.ObjectStreamField;
import java.io.Serializable;

public class Person implements Serializable {
    private static final long serialVersionUID = 1L;
    
    // Transient field (not serialized by default)
    private transient String password;
    
    // Regular fields
    private String name;
    private int age;
    private double salary;
    
    // Define serializable fields explicitly
    private static final ObjectStreamField[] serialPersistentFields = {
        new ObjectStreamField("name", String.class),
        new ObjectStreamField("age", int.class),
        new ObjectStreamField("salary", double.class)
    };
    
    public Person(String name, int age, double salary, String password) {
        this.name = name;
        this.age = age;
        this.salary = salary;
        this.password = password;
    }
    
    @Override
    public String toString() {
        return "Person{name='" + name + "', age=" + age + 
               ", salary=" + salary + ", password='" + password + "'}";
    }
}

此示例显示了一个 Person 类,使用 ObjectStreamField 定义可序列化字段。 password 字段是瞬态的,未包含在内。serialPersistentFields 数组精确控制哪些字段被序列化。

检查字段属性

ObjectStreamField 提供了检查字段特性的方法。这些包括类型信息、基本状态和比较能力。这对于分析序列化形式很有用。

Main.java
import java.io.ObjectStreamField;

public class Main {

    public static void main(String[] args) {
        ObjectStreamField[] fields = {
            new ObjectStreamField("id", long.class),
            new ObjectStreamField("active", boolean.class),
            new ObjectStreamField("title", String.class),
            new ObjectStreamField("data", Object.class, true)
        };
        
        System.out.println("Field inspection:");
        for (ObjectStreamField field : fields) {
            System.out.println("\nField: " + field.getName());
            System.out.println("Type: " + field.getType().getSimpleName());
            System.out.println("Type code: " + field.getTypeCode());
            System.out.println("Primitive: " + field.isPrimitive());
            System.out.println("Unshared: " + field.isUnshared());
        }
        
        // Compare fields
        System.out.println("\nComparison:");
        System.out.println("id vs title: " + fields[0].compareTo(fields[2]));
    }
}

此示例演示了检查 ObjectStreamField 实例的各种属性。它显示了类型代码、基本状态和 unshared 标志。 compareTo 方法显示了如何在序列化期间对字段进行排序。

使用 ObjectStreamField 进行自定义序列化

ObjectStreamField 通过定义字段元数据来实现自定义序列化。结合 writeObjectreadObject,它提供了完全控制。此示例显示了一个完整的实现。

Account.java
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.ObjectStreamField;
import java.io.Serializable;

public class Account implements Serializable {
    private static final long serialVersionUID = 1L;
    
    private String accountNumber;
    private double balance;
    private transient String secretToken;
    
    private static final ObjectStreamField[] serialPersistentFields = {
        new ObjectStreamField("accountNumber", String.class),
        new ObjectStreamField("balance", double.class)
    };
    
    public Account(String accountNumber, double balance, String secretToken) {
        this.accountNumber = accountNumber;
        this.balance = balance;
        this.secretToken = secretToken;
    }
    
    private void writeObject(ObjectOutputStream oos) throws IOException {
        ObjectOutputStream.PutField fields = oos.putFields();
        fields.put("accountNumber", accountNumber);
        fields.put("balance", balance);
        oos.writeFields();
    }
    
    private void readObject(ObjectInputStream ois) 
            throws IOException, ClassNotFoundException {
        ObjectInputStream.GetField fields = ois.readFields();
        accountNumber = (String) fields.get("accountNumber", null);
        balance = fields.get("balance", 0.0);
        secretToken = "REGENERATED"; // Recreate transient field
    }
    
    @Override
    public String toString() {
        return "Account{number='" + accountNumber + "', balance=" + balance + 
               ", token='" + secretToken + "'}";
    }
}

此完整示例显示了使用 ObjectStreamField 的自定义序列化。secretToken 是瞬态的,并被特殊处理。writeObjectreadObject 方法使用定义的字段来精确控制序列化。

比较 ObjectStreamField 实例

ObjectStreamField 实现了 Comparable 以定义字段排序。字段按名称比较,基本类型排在对象类型之前。这会影响序列化顺序。

Main.java
import java.io.ObjectStreamField;

public class Main {

    public static void main(String[] args) {
        ObjectStreamField[] fields = {
            new ObjectStreamField("zField", String.class),
            new ObjectStreamField("aField", int.class),
            new ObjectStreamField("id", long.class),
            new ObjectStreamField("count", Integer.class)
        };
        
        System.out.println("Original order:");
        for (ObjectStreamField field : fields) {
            System.out.println(field.getName() + " (" + field.getTypeCode() + ")");
        }
        
        // Sort fields using natural ordering
        java.util.Arrays.sort(fields);
        
        System.out.println("\nSorted order:");
        for (ObjectStreamField field : fields) {
            System.out.println(field.getName() + " (" + field.getTypeCode() + ")");
        }
        
        // Compare individual fields
        System.out.println("\nComparison results:");
        System.out.println("aField vs zField: " + fields[0].compareTo(fields[2]));
        System.out.println("id vs count: " + fields[1].compareTo(fields[3]));
    }
}

此示例演示了 ObjectStreamField 实例的自然排序。基本字段排在对象字段之前,并且在这些组内按字母顺序排列字段。输出显示了排序顺序和比较结果。

使用类型字符串

ObjectStreamField 为复杂类型提供了类型字符串表示。这些字符串遵循 JVM 类型签名格式。它们对于分析泛型或数组类型很有用。

Main.java
import java.io.ObjectStreamField;
import java.util.List;
import java.util.Map;

public class Main {

    public static void main(String[] args) {
        ObjectStreamField[] fields = {
            new ObjectStreamField("names", String[].class),
            new ObjectStreamField("scores", int[].class),
            new ObjectStreamField("map", Map.class),
            new ObjectStreamField("list", List.class)
        };
        
        System.out.println("Type strings for fields:");
        for (ObjectStreamField field : fields) {
            System.out.println(field.getName() + ": " + field.getTypeString());
        }
        
        // Compare with type codes
        System.out.println("\nType codes vs type strings:");
        for (ObjectStreamField field : fields) {
            System.out.println(field.getName() + 
                " - Code: " + field.getTypeCode() + 
                ", String: " + field.getTypeString());
        }
    }
}

此示例显示了各种字段类型的类型字符串表示。数组和对象类型具有不同的字符串格式。输出将这些与它们对应的类型代码进行比较。类型字符串提供了比类型代码更详细的类型信息。

来源

Java ObjectStreamField 类文档

在本文中,我们介绍了 Java ObjectStreamField 类的基本方法和特性。理解这些概念对于在 Java 应用程序中使用自定义序列化至关重要。

作者

我的名字是 Jan Bodnar,是一位经验丰富的程序员。我从 2007 年开始撰写编程文章,至今已撰写了 1,400 多篇文章和 8 本电子书。凭借超过八年的教学经验,我致力于分享我的知识并帮助他人掌握编程概念。

列出所有Java教程