大家好,欢迎来到IT知识分享网。
Serializable接口的作用
1、什么是序列化与反序列化?
序列化: 1、序列化就是将对象属性转变为二进制数据。2、在网络上进行传输。与序列化相对的是反序列化,它将流转换为对象。这两个过程结合起来,可以轻松地存储和传输数据。把对象转换为字节序列的过程称为对象的序列化,把字节序列恢复为对象的过程称为对象的反序列化。
2、Serializable 简介
实现java.io.Serializable 接口的类是可序列化的,这个序列化接口没有任何方法和域,仅用于标识序列化的语意。 没有实现此接口的类将不能使它们的任意状态被序列化或逆序列化。这个接口其实是个空接口,那么这个序列化操作,到底是由谁去实现了呢?其实,看一下接口的注释说明就知道,当我们让实体类实现Serializable接口时,其实是在告诉JVM此类可被序列化,可被默认的序列化机制序列化。
public interface Serializable { }
3、Serializable 序列化测试
3.1、新建序列化测试类
/** * @Author dw * @ClassName SerializableTest * @Description * @Date 2023/1/2 15:08 * @Version 1.0 */
public class SerializableTest { public static void main(String[] args) { // 初始化
User user = new User(); user.setName("王二"); user.setAge(18); System.out.println(user); // 把对象写到文件中
try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("user.txt"))){ oos.writeObject(user); } catch (IOException e) { e.printStackTrace(); } // 从文件中读出对象
try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream(new File("user.txt")))){ User userRead = (User) ois.readObject(); System.out.println(userRead); } catch (IOException | ClassNotFoundException e) { e.printStackTrace(); } } public static class User { private String name; private Integer age; public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } } }
由于 User没有实现 Serializable 接口,所以系统会报错。运行后报错如下:
顺着堆栈信息,我们来看一下 ObjectOutputStream 的 writeObject0 () 方法。其部分源码如下:
这段代码的意思是,ObjectOutPutStream 在序列化的时候,会判断对象的类型,如果不是字符串、数组、枚举、Serializable 的实例,会抛出 NotSerializableException。但是,如果 SClass 实现了 Serializable 接口的话,就可以被序列化和反序列化了。
3.2、修改User类实现Serialiable接口。
public static class User implements Serializable{ private static final long serialVersionUID = -9085952353374185653L; private String name; private Integer age; public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } }
再次测试, 序列化成功。
3.3、反序列化测试:修改User类中的序列化id, 测试能否序列化成功
public static class User implements Serializable{ private static final long serialVersionUID = -9085952353374185654L; ... }
提示如下错误:
com.dw.study.test.SerializableTest$User@5f184fc6
java.io.InvalidClassException: com.dw.study.test.SerializableTest$User;
local class incompatible: stream classdesc serialVersionUID = -9085952353374185654, local class serialVersionUID = -9085952353374185655
at java.io.ObjectStreamClass.initNonProxy(ObjectStreamClass.java:699)
at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1885)
at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1751)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2042)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1573)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:431)
at com.dw.study.test.SerializableTest.main(SerializableTest.java:31)
serialVersionUID
被称为序列化 ID,它是决定 Java 对象能否反序列化成功的重要因子。在反序列化时,Java 虚拟机会把字节流中的 serialVersionUID
与被序列化类中的 serialVersionUID
进行比较,如果相同则可以进行反序列化,否则就会抛出序列化版本不一致的异常。
// 序列化前的对象名称
public static class User implements Serializable{} // 序列化后的对象名称
public static class MyUser implements Serializable{}
反序列化结果:
提示User类未找到。
4、serialversionuid 默认1L和64位的哈希字段有什么区别?
2.有两种生成方式:
一个是默认的1L,比如:private static final long serialVersionUID = 1L;
一个是根据类名等来生成一个64位的哈希字段
由此可以证明,Java 虚拟机是否允许反序列化,不仅取决于类路径和功能代码是否一致,还有一个非常重要的因素就是序列化 ID 是否一致。
也就是说,如果没有特殊需求,采用默认的序列化 ID(1L)就可以,这样可以确保代码一致时反序列化成功。
6、总结
1. static 和 transient 修饰的字段是不会被序列化的。因为序列化保存的是对象的状态,而 static 修饰的字段属于类的状态,因此可以证明序列化并不保存 static 修饰的字段。
transient 的中文字义为 “临时的”(论英语的重要性),它可以阻止字段被序列化到文件中,在被反序列化后,transient 字段的值被设为初始值,比如 int 型的初始值为 0,对象型的初始值为 null。
2. serialVersionUID 被称为序列化 ID,它是决定 Java 对象能否反序列化成功的重要因子。在反序列化时,Java 虚拟机会把字节流中的 serialVersionUID 与被序列化类中的 serialVersionUID 进行比较,如果相同则可以进行反序列化,否则就会抛出序列化版本不一致的异常。
Java大部分的数据类型都已经实现了可序列化接口。
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://yundeesoft.com/28244.html