Java对象操作流:序列化与反序列化
Posted 流楚丶格念
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java对象操作流:序列化与反序列化相关的知识,希望对你有一定的参考价值。
文章目录
对象操作流
1. 对象序列化流
1.1.1 对象序列化介绍
- 对象序列化:就是将对象保存到磁盘中,或者在网络中传输对象的机制。
- 这种机制就是使用一个字节序列表示一个对象,该字节序列包含:对象的类型、对象的数据和对象中存储的属性等信息。
- 字节序列写到文件(或网络)之后,相当于文件中持久保存了一个对象的信息;反之,该字节序列还可以从文件中读取回来,重构对象,对它进行反序列化。
1.1.2 对象序列化流: ObjectOutputStream
将Java对象的原始数据类型和图形写入OutputStream。 可以使用ObjectInputStream读取(重构)对象。 可以通过使用流的文件来实现对象的持久存储。 如果流是网络套接字流,则可以在另一个主机上或另一个进程中重构对象
构造方法:
方法名 | 说明 |
---|---|
ObjectOutputStream(OutputStream out) | 创建一个写入指定的OutputStream的ObjectOutputStream |
序列化对象的方法:
方法名 | 说明 |
---|---|
void writeObject(Object obj) | 将指定的对象写入ObjectOutputStream |
1.1.3 序列化示例代码
注意事项:一个对象要想被序列化,该对象所属的类必须必须实现Serializable 接口(Serializable是一个标记接口,实现该接口,不需要重写任何方法 )
学生类:
public class Student implements Serializable
private String name;
private int age;
public Student()
public Student(String name, int age)
this.name = name;
this.age = age;
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;
@Override
public String toString()
return "Student" +
"name='" + name + '\\'' +
", age=" + age +
'';
测试类
class ObjectOutputStreamDemo
public static void main(String[] args) throws IOException
//ObjectOutputStream(OutputStream out):创建一个写入指定的OutputStream的ObjectOutputStream
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("StreamFile\\\\oos.txt"));
//创建对象
Student s = new Student("赵丽颖", 18);
//void writeObject(Object obj):将指定的对象写入ObjectOutputStream
oos.writeObject(s);
//释放资源
oos.close();
2. 对象反序列化流
2.1 对象反序列化流: ObjectInputStream
- ObjectInputStream反序列化先前使用ObjectOutputStream编写的原始数据和对象
构造方法
方法名 | 说明 |
---|---|
ObjectInputStream(InputStream in) | 创建从指定的InputStream读取的ObjectInputStream |
反序列化对象的方法
方法名 | 说明 |
---|---|
Object readObject() | 从ObjectInputStream读取一个对象 |
2.2 示例代码
class ObjectInputStreamDemo
public static void main(String[] args) throws IOException, ClassNotFoundException
//ObjectInputStream(InputStream in):创建从指定的InputStream读取的ObjectInputStream
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("StreamFile\\\\oos.txt"));
//Object readObject():从ObjectInputStream读取一个对象
Object obj = ois.readObject();
Student s = (Student) obj;
System.out.println(s.getName() + "," + s.getAge());
ois.close();
3. serialVersionUID&transient
3.0 遇到的问题
用对象序列化流序列化了一个对象后,假如我们修改了对象所属的类文件,读取数据会不会出问题呢?
首先进行序列化操作
再将Bean对象中的private改为public反序列化
会出问题,会抛出InvalidClassException异常
原因分析
仔细阅读错误,他说之前的serialVersionUID与现在的不匹配了
这是因为Java虚拟机会判断如果我们自己没有定义,那么虚拟机会根据类中的信息会自动的计算出一个序列号。当你修改了Bean类的时候,新的类的序列号就会重新计算获得。
关键原因:如果我们修改了类中的信息.那么虚拟机会再次计算出一个序列号。
3.1 serialVersionUID
那我么如何解决上面的问题呢?
那就是不让虚拟机帮我们自动计算,我们自己手动给出.而且这个值不要变.
首先我们要重新序列化,给对象所属的类加一个serialVersionUID
private static final long serialVersionUID = 42L;
运行没毛病
3.2 transient
还要一个问题,如果一个对象中的某个成员变量的值不想被序列化,又该如何实现呢?
给该成员变量加transient关键字修饰,该关键字标记的成员变量不参与序列化过程
如下所示:
4. 示例代码
学生类
测试类
public static void main(String[] args) throws IOException, ClassNotFoundException
Student s1 = new Student("杜子腾",16);
Student s2 = new Student("张三",23);
Student s3 = new Student("李四",24);
// 序列化
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("a.txt"));
oos.writeObject(s1);
oos.writeObject(s2);
oos.writeObject(s3);
oos.close();
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("a.txt"));
Object obj;
/* while((obj = ois.readObject()) != null)
System.out.println(obj);
*/
// 反序列化
while(true)
try
Object o = ois.readObject();
System.out.println(o);
catch (EOFException e)
break;
ois.close();
文件中
以上是关于Java对象操作流:序列化与反序列化的主要内容,如果未能解决你的问题,请参考以下文章