序列化简介
简述
java序列化是将堆内存中存放的java对象放在存放在硬盘或者以字节流的方式在网络中传输。另一种表述:序列化是将结构化的对象数据以非结构的字节流形式存放在本地或者在网络中传输。
【注】:java对象存放在堆内存中,基本数据类型存放在更快的栈内存中,常量存放在常量池中。
与反射的区别是:序列化用于将内存中对象信息放在硬盘中,一般是对象的变量当前值;反射是将硬盘中类信息放在内存中。
实现方式
java序列化的实现方式一般是借助java.io包下的FileOutputStream和ObjectOutputStream类,以及new ObjectOutputStream().writeObject(targetFile)方法。示例:
//1.设置序列化文件目标位置
FileOutputStream fs=new FileOutputStream("E:\\a.bat");
//2.获取ObjectOutputStream对象
ObjectOutputStream os=new ObjectOutputStream(fs);
//3.使用writeObject(Object X);方法将对象数据写入文件;
os.writeObject(obj1);
//4.关闭流,必须且好的编码习惯
os.close();
重要1:序列化与反序列化
要序列化的类必须实现接口Serializable,此接口是个空接口,仅仅用于表示实现改接口的类可以序列化。真正实现序列化的类是ObjectInputStream,ObjectOutputStream。示例如下,将一个对象序列化,然后在读入并打印
package javaX.ioX.SerializableX;
import java.io.*;
/**
* 序列化对象;从磁盘读取硬盘对象;
* @author dugenkui
* on 2017/10/24.
*/
public class TestSerialize implements Serializable{
int varX=1;
String varY ="dugenkuiX";
@Override
public String toString() {
System.out.println(varX+":"+varY);
return varX+varY;
}
public static void main(String[] args) throws IOException {
//序列化此对象;try()中的资源可以在try代码块运行完以后自动释放,不用再X.close()。
// 资源必须实现java.lang.AutoCloseable接口或java.io.Closeable。
try (FileOutputStream fileOutputStream=new FileOutputStream("E:\\a.dat");
ObjectOutputStream os = new ObjectOutputStream(fileOutputStream);) {
os.writeObject(new TestSerialize());
}catch (Exception e){
e.printStackTrace();
}
//读取本地磁盘中序列化的对象,并打印;
try(FileInputStream fs=new FileInputStream("E:\\a.dat");
ObjectInputStream in=new ObjectInputStream(fs)){
TestSerialize object=(TestSerialize)in.readObject();
object.toString();
}catch(ClassNotFoundException x){
x.printStackTrace();
}
}
}
重要2:版本号serialVersionUID
对一个类X对象进行序列化和反序列化是,“发送端”类和“接收端”类都会有一个serialVersionUID/long类型,记录了序列化类的版本号。
private static final long serialVersionUID = 2L;
如果接收端的版本号与发送端的版本号不一致,会抛异常InvalidClassException
和相应的提示。
重要3:序列化对象不保存静态变量
try (FileOutputStream fileOutputStream=new FileOutputStream("E:\\a.dat");
ObjectOutputStream os = new ObjectOutputStream(fileOutputStream);) {
os.writeObject(new TestSerialize());
}catch (Exception e){
e.printStackTrace();
}
staticVar=22;//在序列化对象后在改变静态变量的值,反序列化对象后读取此值,是22。静态变量不能保存在序列化文件中
//读取本地磁盘中序列化的对象,并打印;
try(FileInputStream fs=new FileInputStream("E:\\a.dat");
ObjectInputStream in=new ObjectInputStream(fs)){
TestSerialize object=(TestSerialize)in.readObject();
System.out.println(object.staticVar);//输入22.等于用反序列化的对象调用了本地类的变量。
}catch(ClassNotFoundException x){
x.printStackTrace();
}
重要4:序列化的类必须继承Serializable,如果其父类已经继承他就不用再继承了