java serializable原理_什么是接口,接口的作用

java serializable原理_什么是接口,接口的作用Serializable接口的作用 1、什么是序列化与反序列化? 序列化: 1、序列化就是将对象属性转变为二进制数据。2、在网络上进行传输。与序列化相对的是反序列化,它将流转换为对象。这两个过程结合起来,可以轻松地存储和传输数据。把对象转换为字节序列的过程称为对象的序列化,把字节序列恢复为对象的过程

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 接口,所以系统会报错。运行后报错如下:

java serializable原理_什么是接口,接口的作用

 

 顺着堆栈信息,我们来看一下 ObjectOutputStream 的 writeObject0 () 方法。其部分源码如下:

java serializable原理_什么是接口,接口的作用

   这段代码的意思是,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 进行比较,如果相同则可以进行反序列化,否则就会抛出序列化版本不一致的异常。
 
3.4、反序列化测试序列化前后的对象名称不一致。
// 序列化前的对象名称
 public static class User implements Serializable{} // 序列化后的对象名称
 public static class MyUser implements Serializable{}

反序列化结果:

java 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大部分的数据类型都已经实现了可序列化接口。

 

今天的文章java serializable原理_什么是接口,接口的作用分享到此就结束了,感谢您的阅读,如果确实帮到您,您可以动动手指转发给其他人。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/46937.html

(0)
编程小号编程小号
上一篇 2023-09-05
下一篇 2023-09-05

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注