java的序列化是干什么的

java的序列化究竟是干什么的?

序列化就是一种用来处理对象流的机制,所谓对象流也就是将对象的内容进行流化。可以对流化后的对象进行读写操作,也可将流化后的对象传输于网络之间。序列化是为了解决在对对象流进行读写操作时所引发的问题。

我们知道,java是跨平台语言,为什么跨平台?是因为java程序编译后是class文件,class文件最终被java虚拟机解析成字节码文件,可以运行在任何平台上。

对应的,如果我们想要在网络上进行文字传输,或者想要将程序内存中的对象写入到硬盘,可以用任何的虚拟机进行解析读取。也需要一个共同识别的方式,字节码!!!而我们的java序列化就是将java内存中对象属性的值进行字节码转换。

Java平台允许我们在内存中创建可复用的Java对象,但一般情况下,只有当JVM处于运行时,这些对象才可能存在。即,这些对象的生命周期不会比JVM的生命周期更长。但在现实应用中,就可能要求在JVM停止运行之后能够保存(持久化)指定的对象,并在 将来重新读取 被保存的对象。Java对象序列化就能够帮助我们实现该功能。必须注意地是,对象序列化保存的是对象的"状态",即它的成员变量。

由此可知,对象序列化不会关注类中的 静态变量。

除了在持久化对象时会用到对象序列化之外,当使用RMI(远程方法调用),或在网络中传递对象时,都会用到对象序列化。Java序列化API为处理对象序列化提供了一个标准机制。

那么序列化的字节码和.class文件字节码是否是一样的呢?答案否。

序列化保存的是对象属性的值。由程序解析使用。

class字节码是类的属性信息(类型、作用域、static或非static)和方法的信息(方法的签名信息、方法体的内容)及其他信息,由虚拟机解析使用。

简而言之:序列化的作用就是为了 不同jvm之间 共享实例对象 的一种解决方案.由java提供此机制,效率之高,是其他解决方案无法比拟的.

为什么要序列化和反序列化

我们知道,当两个进程进行远程通信时,可以相互发送各种类型的数据,包括文本、图片、音频、视频等, 而这些数据都会以二进制序列的形式在网络上传送。那么当两个Java进程进行通信时,能否实现进程间的对象传送呢?答案是可以的。如何做到呢?这就需要Java序列化与反序列化了。换句话说,一方面,发送方需要把这个Java对象转换为字节序列,然后在网络上传送;另一方面,接收方需要从字节序列中恢复出Java对象。当我们明晰了为什么需要Java序列化和反序列化后,我们很自然地会想Java序列化的好处。其好处一是实现了数据的持久化,通过序列化可以把数据永久地保存到硬盘上(通常存放在文件里),二是,利用序列化实现远程通信,即在网络上传送对象的字节序列。

如何实现java序列化?

1. 基于Serializable接口的序列化。
 Java中,只要一个类实现了java.io.Serializable接口,那么它就可以被序列化。

如果仅仅只是让某个类实现Serializable接口,而没有其它任何处理的话,则就是使用 默认序列化机制。使用默认机制,在序列化对象时,不仅会序列化当前对象本身,还会对该对象引用的其它对象也进行序列化,同样地,这些其它对象引用的另外对象也将被序列化,以此类推。所以,如果一个对象包含的成员变量是容器类对象,而这些容器所含有的元素也是容器类对象,那么这个序列化的过程就会较复杂,开销也较大。

@Transient 关键字:当某个字段被声明为@Transient后,默认序列化机制就会忽略该字段。

2.基于Externalizable接口的序列化

Externalizable继承于Serializable,当使用该接口时,序列化的细节需要由程序员去完成。
要对writeExternal()与readExternal()方法进行手动处理。

涉及到的javaAPI

java.io.ObjectOutputStream表示对象输出流,它的writeObject(Object obj)方法可以对参数指定的obj对象进行序列化,把得到的字节序列写到一个目标输出流中。

java.io.ObjectInputStream表示对象输入流,它的readObject()方法源输入流中读取字节序列,再把它们反序列化成为一个对象,并将其返回。

只有实现了Serializable或Externalizable接口的类的对象才能被序列化,否则抛出异常。

序列化和反序列化的步骤

序列化:
步骤一:创建一个对象输出流,它可以包装一个其它类型的目标输出流,如文件输出流:

 ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(“目标地址路径”));

步骤二:通过对象输出流的writeObject()方法写对象:

out.writeObject("Hello");
out.writeObject(new Date());

反序列化:
步骤一:创建一个对象输入流,它可以包装一个其它类型输入流,如文件输入流:

 ObjectInputStream in = new ObjectInputStream(new fileInputStream(“目标地址路径”));

步骤二:通过对象输出流的readObject()方法读取对象:

 String obj1 = (String)in.readObject();
 Date obj2 =  (Date)in.readObject();

说明:为了正确读取数据,完成反序列化,必须保证向对象输出流写对象的顺序与从对象输入流中读对象的顺序一致。

猜你喜欢

转载自blog.csdn.net/qq_44918331/article/details/112230400