在深拷贝与浅拷贝中,提到可以采用「序列化与反序列化」的方式来实现深拷贝,今天主要来填一下序列化的坑。
其中,序列化是一种对象持久化的手段,普遍应用于网络传输和远程方法调用(RMI)等场景中,建议关注。
参考答案:
在Java中,序列化是指将Java对象转换为字节序列的过程,而反序列化是指将字节序列转换为Java对象的过程。其中,字节序列即是二进制数据,可以方便地在网络上传输或存储到本地硬盘中。
问题分析:可以从序列化和反序列化的主要作用或应用场景进行总结。
参考答案:
序列化的主要作用包括两个方面:
主要应用场景:
备注:当然还有很多应用场景,在此仅做参考。
问题分析:同「请解释一下Serializable接口的作用」。
参考答案:
第一步:将需要序列化的对象所属类实现java.io.Serializable标记接口(没有任何抽象方法的接口)。
public class Person implements Serializable {
private static final long serialVersionUID = -7755892886656448346L;
private String name;
private Integer age;
// getter、setter、constructor和toString方法省略
}
第二步:在Java程序中使用对象输出流(ObjectOutputStream),通过其writeObject()方法来实现序列化操作。
OutputStream out = new FileOutputStream("D:\\Jerry.txt");
ObjectOutputStream oos = new ObjectOutputStream(out);
oos.writeObject(new Person("Jerry", 18));
oos.flush();
第三步:在Java程序中使用对象输入出流(ObjectInputStream),通过其readObject()方法来实现反序列化操作。
InputStream is = new FileInputStream("D:\\Jerry.txt");
ObjectInputStream ois = new ObjectInputStream(is);
Person jerry = (Person) ois.readObject();
常见问题:
问:如何实现自定义序列化策略?
方式一:实现Externalizable接口,并重写WriteExternal(ObjectOutput)和readExternal(ObjectInput)方法。其中,Externalizable接口继承了Serializable接口,并添加了以上两个方法,用于实现对序列化的控制。
方式二:根据Externalizable接口的思想,可在实现Serializable接口的基础上,直接添加并实现WriteObject(ObjectOutputStream)和readObject(ObjectInputStream)两个方法。
其中,ArrayList类即采用方式二来实现对序列化的控制,主要是为了保证仅对动态数组中的非null元素进行序列化。
问:serialVersionUID常量有什么作用?
答:保证版本号的一致性。若不显式指定该常量值,Java编译器会自动为其生成一个默认值,该默认值会随着类代码的变动而变动。故当修改类代码时,之前已经序列化的对象在进行反序列化时即会因为版本号的不一致而发生异常。
显式定义serialVersionUID主要有两种用途:
问:序列化为什么可以实现深拷贝?
答:若一个对象的属性引用其他对象,则序列化该对象时引用对象也会同时被序列化,这即是序列化能够实现深拷贝的本质。
Java名企面试吧,每天10点24分,我们不见不散!
丙子先生的宗旨是,每天以短篇幅讲高频面试题,不增加太多负担,但需要持之以恒。
能力有限,欢迎指教!