两个Java进程进行通信时实现进程间的对象传送需要Java序列化与反序列化。
对象(object)是类(class)的一个实例(instance)。一个类中包含了变量(field)和函数(method)两个部分。同一个 类的不同对象只是变量不同,所以Java API序列化过程中只保存了对象的变量部分。同样,由于静态变量(static field)是由同一个类的各个对象共用的,所以序列化过程中也不保存。
1、序列化和反序列化:Java序列化是指把Java对象转换为字节序列的过程,而Java反序列化是指把字节序列恢复为Java对象的过程。
1.1、序列化: 把对象转换成有序字节流,以便在网络上传输或者保存在本地磁盘中。对象序列化的最主要的用处就是在传递和保存对象的时候,保证对象的完整性和可传递性。
1.2、反序列化:把字节序列恢复为Java对象的过程。
2、Java序列化的好处:
1)永久性保存对象,保存对象的字节序列到本地文件或者数据库中;
2)通过序列化以字节流的形式使对象在网络中进行传递和接收;
3)通过序列化在进程间传递对象。
3、实现序列化的要求:
只有实现了Serializable或Externalizable接口的类的对象才能被序列化,否则抛出异常!实现接口无须实现任何方法,只是表明该类的实例时可以序列化的。Externalizable接口继承自 Serializable接口,实现Externalizable接口的类完全由自身来控制序列化的行为,而仅实现Serializable接口的类可以 采用默认的序列化方式 。
在Java API中,对象序列化接口主要由两个类提供:ObjectOutputStream,ObjectInputStream。
4、序列化实现
4.1、序列化
1)创建一个对象输出流,它可以包装一个其它类型的目标输出流,如文件输出流;
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("D:/Person.txt"));
2)调用输出流ObjectOutputStream对象的writeObject()方法写对象。
oos.writeObject(person);
4.2、反序列化
1)创建ObjectOutputStream流对象,是一个处理流;
ObjectInputStream in = new ObjectInputStream(new FileInputStream(
new File("D:/Person.txt")));
2)调用ObjectInputStream对象的readObject()方法读取流中的对象,返回一个object类型的Java对象。
Person person = (Person) in.readObject();
5、自定义序列化
在属性前面加transient关键字,可以指定Java序列化时无需理会该属性。被其修饰的属性被完全隔离在序列化机制之外,恢复的时候无法取得该值。
6、serialVersionUID的作用:
6.1、serialVersionUID是对类进行版本控制的,Java的序列化机制是通过判断类的serialVersionUID来验证版本一致性的。在进行反序列化时,JVM会把传来的字节流中的serialVersionUID与本地相应实体类的serialVersionUID进行比较,如果相同就认为是一致的,可以进行反序列化,否则就会出现序列化版本不一致的异常,即是InvalidCastException。
6.2、serialVersionUID有两种生成方式:
1)默认的1L,比如:private static final long serialVersionUID = 1L;
2)根据类名、接口名、成员方法及属性等来生成一个64位的哈希字段。
参考:
https://blog.youkuaiyun.com/gsn2167/article/details/78095045
https://www.cnblogs.com/wxgblogs/p/5849951.html
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
public class WriteObject
{
public static void main(String[] args)
{
SerializePerson(); // 序列化Person对象
DeserializePerson();// 反序列化
}
private static void SerializePerson()
{
ObjectOutputStream oos = null;
try
{
// 创建一个输出流
oos = new ObjectOutputStream(new FileOutputStream("D:/Person.txt"));
Person person = new Person("孙悟空", 500, "男");
// 将person对象写入输出流
oos.writeObject(person);
} catch (IOException ex)
{
ex.printStackTrace();
} finally
{
try
{
if (oos != null)
{
System.out.println("Person对象序列化成功!");
oos.close();
}
} catch (IOException ex)
{
ex.printStackTrace();
}
}
}
private static void DeserializePerson()
{
ObjectInputStream ois = null;
try
{
// 创建一个输入流
ois = new ObjectInputStream(new FileInputStream("D:/Person.txt"));
// 从输入流读取Java对象,并转化为Person
Person person = (Person) ois.readObject();
System.out.println("名字:" + person.getName() + ",年龄:"
+ person.getAge() + ",性别:" + person.getSex());
} catch (Exception ex)
{
ex.printStackTrace();
} finally
{
try
{
if (ois != null)
{
System.out.println("反序列化成功!");
ois.close();
}
} catch (IOException ex)
{
ex.printStackTrace();
}
}
}
}
class Person implements Serializable
{
private static final long serialVersionUID = -5809782578272943999L;
private String name;
private int age;
private transient String sex;// 自定义,不序列化
public Person(String name, int age, String sex)
{
super();
this.name = name;
this.age = age;
this.sex = sex;
}
public String getName()
{
return name;
}
public void setName(String name)
{
this.name = name;
}
public int getAge()
{
return age;
}
public void setAge(int age)
{
this.age = age;
}
public String getSex()
{
return sex;
}
public void setSex(String sex)
{
this.sex = sex;
}
}
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.text.MessageFormat;
public class TestObjSerializeAndDeserialize
{
public static void main(String[] args) throws Exception
{
SerializePerson(); // 序列化Person对象
Person p = DeserializePerson(); // 反序列Perons对象
System.out.println(MessageFormat.format("name={0},age={1},sex={2}", p.getName(), p.getAge(), p.getSex()));
}
/*
* 步骤一:创建一个对象输出流,它可以包装一个其它类型的目标输出流,如文件输出流:
* ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("D:\\object.out"));
* 步骤二:通过对象输出流的writeObject()方法写对象:
* oos.writeObject(new User("xuliugen", "123456", "male"));
*/
private static void SerializePerson() throws FileNotFoundException,IOException
{
Person person = new Person();
person.setName("asd");
person.setAge(26);
person.setSex("男");
// ObjectOutputStream,创建一个流对象,比如文件输出流对象
// 对象输出流,将Person对象存储到E盘的Person.txt文件中,完成对Person对象的序列化操作
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(
new File("D:/Person.txt")));
out.writeObject(person);
System.out.println("Person对象序列化成功!");
out.close();
}
/*
* 步骤一:创建一个对象输入流,它可以包装一个其它类型输入流,如文件输入流:
* ObjectInputStream ois= new ObjectInputStream(new FileInputStream("object.out"));
* 步骤二:通过对象输出流的readObject()方法读取对象:User user = (User) ois.readObject();
*/
private static Person DeserializePerson() throws Exception, IOException
{
ObjectInputStream in = new ObjectInputStream(new FileInputStream(
new File("D:/Person.txt")));
Person person = (Person) in.readObject();
System.out.println("Person对象反序列化成功!");
return person;
}
}
class Person implements Serializable
{
/**
* 序列化ID
*/
private static final long serialVersionUID = -5809782578272943999L;
private int age;
private String name;
private String sex;
public int getAge()
{
return age;
}
public String getName()
{
return name;
}
public String getSex()
{
return sex;
}
public void setAge(int age)
{
this.age = age;
}
public void setName(String name)
{
this.name = name;
}
public void setSex(String sex)
{
this.sex = sex;
}
}