博主18年的互联网软件开发经验,从一名程序员小白逐步成为了一名架构师,我想通过平台将经验分享给大家,因此博主每天会在各个大牛网站点赞量超高的博客等寻找该技术栈的资料结合自己的经验,晚上进行用心精简、整理、总结、定稿,每天都会整理到12点,为了就是能让大家能够真正了解该技术栈的真正原理,最终从程序员成为一名真正的架构师,写的不一定是全站做好的,但是是全站最用心的~。
以后我会推出一些列的文章,每天都会更新,每天进步一点点,发布顺序【java的api基础、应用、实战】->【java开源技术栈及源码分析】->【java开源技术栈整合】->【java低代码开发平台的建设】
关注【架构师成长之道】 输入“java基础课程”,即可免费获得全套架构师全套课程
一、java.io
1.53 ObjectStreamField
ObjectStreamField
类用于描述一个序列化类的字段。它提供了关于字段的名称、类型和序列化标志的信息。以下是关于 ObjectStreamField
的详细介绍:
ObjectStreamField 类介绍:
所有字段:
-
static final char TYPE_BOOLEAN
: 表示布尔类型的字段。 -
static final char TYPE_BYTE
: 表示字节类型的字段。 -
static final char TYPE_CHAR
: 表示字符类型的字段。 -
static final char TYPE_SHORT
: 表示短整型类型的字段。 -
static final char TYPE_INT
: 表示整型类型的字段。 -
static final char TYPE_LONG
: 表示长整型类型的字段。 -
static final char TYPE_FLOAT
: 表示浮点型类型的字段。 -
static final char TYPE_DOUBLE
: 表示双精度浮点型类型的字段。 -
static final char TYPE_OBJECT
: 表示对象类型的字段。 -
static final char TYPE_ARRAY
: 表示数组类型的字段。
构造方法:
-
ObjectStreamField(String name, Class<?> type)
: 使用指定名称和类型创建一个ObjectStreamField
实例。 -
ObjectStreamField(String name, Class<?> type, boolean unshared)
: 使用指定名称、类型和序列化标志创建一个ObjectStreamField
实例。
方法摘要:
-
String getName()
: 返回字段的名称。 -
Class<?> getType()
: 返回字段的类型。 -
boolean isPrimitive()
: 判断字段是否是原始类型。 -
boolean isUnshared()
: 判断字段是否是非共享的。
简单使用例子:
下面是一个简单的使用示例,演示了如何创建和使用 ObjectStreamField
实例:
javaCopy code import java.io.ObjectStreamField; import java.util.Arrays; public class ObjectStreamFieldExample { public static void main(String[] args) {// 创建 ObjectStreamField 实例ObjectStreamField field1 = new ObjectStreamField("name", String.class);ObjectStreamField field2 = new ObjectStreamField("age", int.class, true); // 打印字段信息System.out.println("Field Name: " + field1.getName());System.out.println("Field Type: " + field1.getType().getSimpleName());System.out.println("Is Primitive: " + field1.isPrimitive());System.out.println("Is Unshared: " + field1.isUnshared()); System.out.println(); System.out.println("Field Name: " + field2.getName());System.out.println("Field Type: " + field2.getType().getSimpleName());System.out.println("Is Primitive: " + field2.isPrimitive());System.out.println("Is Unshared: " + field2.isUnshared()); // 获取 ObjectStreamField 数组ObjectStreamField[] fields = {field1, field2};System.out.println("All Fields: " + Arrays.toString(fields));} }
在这个示例中,我们首先创建了两个 ObjectStreamField
实例,一个表示名为 "name" 的字符串字段,另一个表示名为 "age" 的整型字段。然后,我们打印了这些字段的名称、类型、是否为原始类型以及是否为非共享字段。最后,我们创建了一个 ObjectStreamField
数组,并打印出所有字段。
应用场景
ObjectStreamField
主要用于在序列化和反序列化过程中描述类的字段信息。它通常与 ObjectStreamClass
类一起使用,以便在序列化和反序列化过程中了解类的结构。以下是一些可能的应用场景及相应的代码实现:
应用场景 1: 自定义序列化格式
有时候,你可能需要自定义序列化格式以适应特定的需求,例如,你可能想要跳过某些字段的序列化,或者使用不同的字段名。在这种情况下,你可以使用 ObjectStreamField
来描述你所需的字段,并在序列化和反序列化过程中相应地处理它们。
javaCopy code import java.io.*; public class CustomSerializationExample { public static void main(String[] args) {// 创建一个对象,准备进行序列化User user = new User("Alice", "12345"); // 将字段描述传递给序列化方法ObjectStreamField[] fields = {new ObjectStreamField("username", String.class),new ObjectStreamField("password", String.class)}; try {// 进行自定义序列化serializeObject(user, fields, "user.ser");} catch (IOException e) {e.printStackTrace();} // 从文件中反序列化对象try {User loadedUser = deserializeObject("user.ser");System.out.println("Loaded user: " + loadedUser);} catch (IOException | ClassNotFoundException e) {e.printStackTrace();}} private static void serializeObject(User user, ObjectStreamField[] fields, String filename) throws IOException {ObjectOutputStream outputStream = new ObjectOutputStream(new FileOutputStream(filename)) {@Overrideprotected void writeStreamHeader() throws IOException {// 覆盖默认的头部写入方法,不写入头部信息}}; // 写入自定义字段描述outputStream.writeFields();outputStream.writeUnshared(user); // 写入对象outputStream.close();} private static User deserializeObject(String filename) throws IOException, ClassNotFoundException {ObjectInputStream inputStream = new ObjectInputStream(new FileInputStream(filename)) {@Overrideprotected ObjectStreamClass readClassDescriptor() throws IOException, ClassNotFoundException {// 覆盖默认的类描述符读取方法,返回自定义的描述符return ObjectStreamClass.lookup(User.class);}}; // 读取自定义字段描述inputStream.readFields(); // 读取对象User user = (User) inputStream.readUnshared();inputStream.close(); return user;} } // 用户类 class User implements Serializable {private static final long serialVersionUID = 1L;private String username;private String password; public User(String username, String password) {this.username = username;this.password = password;} @Overridepublic String toString() {return "User{" +"username='" + username + '\'' +", password='" + password + '\'' +'}';} }
在这个示例中,我们使用了自定义的序列化和反序列化方法,其中涉及 ObjectStreamField
类。我们创建了一个 User
类表示用户对象,然后在序列化时指定了要序列化的字段,并在反序列化时指定了要加载的字段。这样,我们就可以灵活地控制序列化和反序列化过程,从而实现自定义的序列化格式。
实战例子
下面是一个简单的项目实战例子,演示了如何使用 ObjectStreamField
类自定义序列化和反序列化过程。
假设我们有一个系统,需要存储用户的敏感信息,但不希望将密码字段序列化到文件中。在这种情况下,我们可以使用 ObjectStreamField
来指定哪些字段应该被序列化,哪些字段应该被忽略。
javaCopy code import java.io.*; // 用户类 class User implements Serializable {private static final long serialVersionUID = 1L; // 用于自定义序列化格式的字段描述private static final ObjectStreamField[] serialPersistentFields = {new ObjectStreamField("username", String.class),new ObjectStreamField("email", String.class)}; // 用户名和邮箱字段不可序列化private transient String username;private transient String password;private transient String email; public User(String username, String password, String email) {this.username = username;this.password = password;this.email = email;} // 重写 writeObject 方法,手动控制序列化过程private void writeObject(ObjectOutputStream out) throws IOException {ObjectOutputStream.PutField fields = out.putFields();fields.put("username", username);fields.put("email", email);out.writeFields();} // 重写 readObject 方法,手动控制反序列化过程private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {ObjectInputStream.GetField fields = in.readFields();username = (String) fields.get("username", "");email = (String) fields.get("email", "");} @Overridepublic String toString() {return "User{" +"username='" + username + '\'' +", email='" + email + '\'' +'}';} } public class ObjectStreamFieldExample { public static void main(String[] args) {// 创建用户对象User user = new User("Alice", "password123", "alice@example.com"); // 将用户对象保存到文件try (ObjectOutputStream outputStream = new ObjectOutputStream(new FileOutputStream("user.ser"))) {outputStream.writeObject(user);System.out.println("User saved successfully.");} catch (IOException e) {e.printStackTrace();} // 从文件中加载用户对象try (ObjectInputStream inputStream = new ObjectInputStream(new FileInputStream("user.ser"))) {User loadedUser = (User) inputStream.readObject();System.out.println("Loaded user: " + loadedUser);} catch (IOException | ClassNotFoundException e) {e.printStackTrace();}} }
在这个示例中,我们定义了一个 User
类,其中包含了用户名、密码和邮箱字段。我们使用 transient
关键字将这些字段标记为不可序列化。然后,我们在类中重写了 writeObject
和 readObject
方法,手动控制了序列化和反序列化过程,只序列化了需要的字段。
这个示例演示了如何使用 ObjectStreamField
类自定义序列化和反序列化过程,以便更灵活地控制对象的序列化行为。