含Object与Uri成员的类如何实现Serializable及序列化Object类型成员
序列化包含Object和Uri类型成员的Serializable类
Alright, let's break this down step by step. If you're trying to implement Serializable for a class that has both Object and Uri members, there are a few gotchas to tackle—since not all objects play nice with serialization, and Uri (especially the Android framework's version) isn't serializable out of the box.
1. 处理Object类型成员的序列化
Serializable的核心规则是:所有非transient成员变量要么本身可序列化,要么你需要手动处理它们的序列化逻辑。针对Object成员,你可以这样做:
- 如果你的
Object指向的是已经实现Serializable的类(比如String、Integer,或者你自己标记为可序列化的自定义类),默认序列化机制会自动处理它,不需要额外操作。 - 如果这个
Object可能指向不可序列化的类,有两个选择:- 把它标记为
transient:这会告诉序列化器跳过这个字段,但反序列化时该字段会被设为null,你需要在readObject()方法里添加恢复逻辑。 - 实现自定义序列化逻辑:通过私有方法
writeObject()和readObject()手动控制Object的读写流程。比如先检查对象是否可序列化,再决定如何写入;或者将其转换为可序列化的格式(比如字符串)存储。
- 把它标记为
2. 处理Uri类型成员的序列化
Android的Uri类并没有实现Serializable,如果直接把它作为普通成员,序列化时会抛出NotSerializableException。最简洁的解决方式是:
- 把
Uri转换成字符串形式(用uri.toString())进行序列化,反序列化时再通过Uri.parse()解析回Uri对象。 - 你可以选择两种实现方式:
- 给
Uri字段标记transient,同时新增一个String字段存储它的字符串值; - 用自定义的
writeObject()/readObject()方法直接处理转换逻辑(这种方式更简洁,不需要额外字段)。
- 给
3. 完整示例代码
下面是一个完整的类示例,它实现了Serializable,同时处理了Object和Uri成员的序列化需求:
import android.net.Uri; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; public class MySerializableClass implements Serializable { // Object成员:可能指向可序列化对象 private Object dataObject; // Uri成员:标记为transient,因为Uri本身不可序列化 private transient Uri contentUri; // 构造方法 public MySerializableClass(Object dataObject, Uri contentUri) { this.dataObject = dataObject; this.contentUri = contentUri; } // 自定义序列化方法(JVM会自动调用) private void writeObject(ObjectOutputStream out) throws IOException { // 先使用默认逻辑序列化所有非transient字段 out.defaultWriteObject(); // 手动将Uri序列化为字符串 out.writeObject(contentUri != null ? contentUri.toString() : null); // 处理Object成员:先检查是否可序列化再写入 if (dataObject instanceof Serializable) { out.writeObject(dataObject); } else { // 如果不可序列化,写入null(也可以根据需求添加自定义 fallback 逻辑) out.writeObject(null); } } // 自定义反序列化方法(JVM会自动调用) private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { // 先使用默认逻辑反序列化所有非transient字段 in.defaultReadObject(); // 从字符串恢复Uri对象 String uriString = (String) in.readObject(); contentUri = uriString != null ? Uri.parse(uriString) : null; // 恢复Object成员 dataObject = in.readObject(); // 如果需要重构不可序列化对象,可以在这里添加对应的逻辑(比如利用保存的元数据) } // Getter方法 public Object getDataObject() { return dataObject; } public Uri getContentUri() { return contentUri; } }
4. 关键注意事项
writeObject()和readObject()方法必须是私有的——JVM会识别这些方法签名并自动调用,不需要你手动触发。- 如果你的类有父类,父类要么实现
Serializable,要么有无参构造方法(因为如果父类不可序列化,反序列化时会调用它的无参构造)。 - 对于Android开发,
Parcelable在进程间通信中通常比Serializable更高效,但如果确实需要用Serializable(比如持久化到磁盘),上面的方案完全适用。 - 一定要测试你的序列化/反序列化流程,覆盖边缘情况(比如
Uri为null、Object指向不可序列化类的场景)。
内容的提问来源于stack exchange,提问作者Aditya Arora
相关产品推荐
相关产品推荐

