今天了解了RPC调用的一些基本原理和介绍,对于在远程调用方法的时候对象的传输中序列化serializabel的作用也更加清晰,故记录下
很多人觉得自己写得 Java 代码中,新建的 pojo 对象要实现序列化是为了要保存到硬盘上,其实呢,实现序列化和保存到硬盘上没有必然的关系。
- 很多人在初学序列化操作的时候,一般都是理解为对象通过序列化保存在磁盘上的字节流文件,后又通过字节流反向读取为对象。
- 我们将 Java对象转换成公共的格式叫做序列化,将公共的格式转换成对象叫做反序列化。保存到磁盘只是序列化的一种表现形式。
实现序列化的原因
- 将对象的状态保存在存储媒体中以便可以在以后重新创建出完全相同的副本
- 将对象从一个应用程序域发送至另一个应用程序域。实现serializabel接口的作用是就是可以把对象存到字节流,然后可以恢复,而网络传输的基础则是字节流,故既可以远程传输,又可以本地化恢复。(Ps:不实现序列化接口得话,服务器并不能识别其为对象类型,这是关键)
什么时候需要序列化
- 当你想用套接字在网络上传送对象的时候;
- 当你想把的内存中的对象写入到硬盘的时候;
- 当你想通过RMI传输对象的时候;(远程调用方法,如RPC)
Json和serializabel对比
- 长度方面,Json比serializabel小
- 速度方面,Json比serializabel快,但序列化算法好像并不止一种
- 表示方面,Json一般表示字符串,如果前端要将其处理为对象,需要额外的处理,而serializabel则直接恢复
Json和serializabel选择
序列化使用serialize,特别是对象的存储。这是其存在的意义。
与对象无关的数据存储可以使用json,如包含大量数字的数组等。只是当遇到这种情况,我们需要做的可能是重构数据库了。
数据交换时使用JSON,这也是其定义所在。
目前JSON是能用于UTF-8编码的数据
Java序列化的相关知识点
- Java序列化有两种方式,一种是实现Serializable接口。
- 另一种是实现Exteranlizable接口。而实现Exteranlizable接口的时候,我们需要重写writeExternal和readExternal方法,它的效率比Serializable高一些,并且可以决定哪些属性需要序列化(即使是transient修饰的),但是对大量对象,或者重复对象,则效率低。
-
静态变量是不会被序列化的,即使没有transient关键字修饰
serializabel的例子
对象
import java.io.*;
public class Employee implements Serializable //实现了序列化
{
public String name;
public String address;
public transient int SSN; //transient等下再讲
public int number;
public void mailCheck() {
System.out.println("Mailing a check to " + name
+ " " + address);
}
}
序列化
import java.io.*;
class SerializeDemo
{
public static void main(String [] args)
{
Employee e = new Employee();
e.name = "Reyan Ali";
e.address = "Phokka Kuan, Ambehta Peer";
e.SSN = 11122333;
e.number = 101;
try
{
FileOutputStream fileOut =
new FileOutputStream("C:\\Users\\Ryan\\Desktop\\obj.ser");
ObjectOutputStream out = new ObjectOutputStream(fileOut);
out.writeObject(e);
out.close();
fileOut.close();
System.out.printf("Serialized data is saved in obj.ser");
}catch(IOException i)
{
i.printStackTrace();
}
}
}
反序列化
import java.io.*;
public class Deserializable
{
public static void main(String [] args)
{
Employee e = null;
try
{
FileInputStream fileIn = new FileInputStream("C:\\Users\\Ryan\\Desktop\\obj.ser");
ObjectInputStream in = new ObjectInputStream(fileIn);
e = (Employee) in.readObject();
in.close();
fileIn.close();
}catch(IOException i)
{
i.printStackTrace();
return;
}catch(ClassNotFoundException c)
{
System.out.println("Employee class not found");
c.printStackTrace();
return;
}
System.out.println("Deserialized Employee...");
System.out.println("Name: " + e.name);
System.out.println("Address: " + e.address);
System.out.println("SSN: " + e.SSN);
System.out.println("Number: " + e.number);
}
}
彩蛋
transient关键字修饰的变量反序列失败噢。