8.11 Java 序列化 与 反序列化

什么是序列化?

Java序列化是一种将对象转换为字节流的过程,以便在网络上传输或在文件中存储对象。
序列化可以将对象的状态保存到磁盘或通过网络传输,
然后可以通过反序列化重新创建对象,
使得对象的状态能够在不同的环境中进行传递和存储。

do shi te 要用序列化?

  • 网络传输:通过序列化,可以将对象转换为字节流,在网络上传输。在客户端和服务器之间传递对象数据时,可以将对象序列化为字节流,通过网络传输,在接收端进行反序列化还原为对象。
  • 持久化存储:通过序列化,可以将对象保存到文件或数据库中,实现对对象的持久化存储。在需要保存对象状态的时候,将对象序列化到存储介质中,可以实现数据的长期保存和读取。
  • 跨平台通信:Java序列化是一种平台无关的机制,可以将对象序列化为字节流后,在不同的平台上进行传输和传递。这意味着使用Java序列化,可以在不同的操作系统和编程语言之间实现对象的交互通信。

序列化是Java跨平台强大的很大一个部分原因!!!

Java的跨平台性是由多个因素共同作用而实现的,其中序列化确实是其中一个重要的方面之一,但并不是全部。以下是一些影响Java跨平台性的因素:

字节码:Java编译器将Java源代码编译为字节码,而不是针对特定的硬件或操作系统生成机器码。这种字节码的特性使得Java程序能够在不同的平台上运行。

JVM(Java虚拟机):Java字节码通过JVM来执行。JVM是针对特定平台的软件,负责将字节码解释或编译为特定平台的机器码。通过JVM的存在,Java程序能够在不同的操作系统和硬件平台上运行。

标准库:Java标准库提供了丰富的跨平台API,使得开发者能够编写与平台无关的代码。Java标准库提供了跨平台的网络、IO、图形界面等功能,使得开发者能够以相似的方式操作不同的底层平台。

序列化:作为Java的重要特性之一,序列化确实提供了一种跨平台的对象交换方式。通过序列化,可以将对象转换为字节流进行传输或存储,使得对象的状态能够在不同的环境中传递和存储。这为数据的跨平台传输和存储提供了方便。

要序列化的前提条件:

实现 java.io.Serializable接口


public class Employee implements java.io.Serializable
{
   public String name;
   public String address;
   public transient int SSN;
   public int number;
   public void mailCheck()
   {
      System.out.println("Mailing a check to " + name
                           + " " + address);
   }
}

序列化

请注意,一个类的对象要想序列化成功,必须满足两个条件:

该类必须实现 java.io.Serializable 接口。

该类的所有属性必须是可序列化的。如果有一个属性不是可序列化的,则该属性必须注明是短暂的。

如果你想知道一个 Java 标准类是否是可序列化的,请查看该类的文档。检验一个类的实例是否能序列化十分简单, 只需要查看该类有没有实现 java.io.Serializable接口。

import java.io.*;

public class Mine{
	public static void main(String [] args)
	   {
	      Employee e = new Employee();
	      e.name = "Kasaki Nozomi";
	      e.address = "Japan, Kitauji";
	      e.SSN = 11122333;
	      e.number = 1203;
	      try
	      {
	         FileOutputStream fileOut =
	         new FileOutputStream("employee.ser");
	         ObjectOutputStream out = new ObjectOutputStream(fileOut);
	         out.writeObject(e);
	         out.close();
	         fileOut.close();
	         System.out.printf("Serialized data is saved in /tmp/employee.ser");
	      }catch(IOException i)
	      {
	          i.printStackTrace();
	      }
	   }
}

反序列化

import java.io.*;

public class Deserialized {
	static <T> void pln(T x) {
		System.out.println(x);
	} 
	public static void main(String[] args) {
		Employee e = null;
		try {
			FileInputStream fileIn = new FileInputStream("employee.ser");
			ObjectInputStream in = new ObjectInputStream(fileIn);
			e = (Employee) in.readObject();
			in.close();
			fileIn.close();
		} catch (IOException e1) {
			e1.printStackTrace();
			return;
		}catch (ClassNotFoundException e2) {
			System.out.printf("[%s] class not found.",e.getClass());
			e2.printStackTrace();
			return;
		}
		pln("Deserialized Employee...");
		pln("Name: " + e.name);
		pln("Address: " + e.address);
	}
}

关于 transient:

  • 序列化的时候 用transient修饰的数据(密码等隐私数据) 不会被JVM序列化
  • 线程不安全变量: 当一个成员变量在多线程环境下被访问并修改时,为了保证线程安全,可以将该成员变量声明为 transient,这样每个线程都将使用自己的本地副本,避免了对数据的冲突访问。
  • 内存缓存:有时候,我们会使用缓存来提高程序的性能,但是缓存通常不需要被持久化,可以将缓存字段声明为 transient,这样在对象持久化的过程中不会保存缓存的内容。
  • 非序列化框架:有些第三方框架在进行对象序列化时会自动忽略 transient 字段,例如 Jackson、Gson 等。如果你希望某些字段在使用这些框架进行序列化时被忽略,可以将它们声明为 transient。

不得不说GPT对学习真的有极大的帮助!大部分都不用在网上找无用信息了

posted @ 2023-08-11 18:10  N0zoM1z0  阅读(8)  评论(0编辑  收藏  举报