标签:static dex shu 修改 使用 vat rgs 示例 final
序列化指将Java对象转换成字节序列, 这些字节序列可以保存在磁盘上, 或者进行网络传输。反序列化即指将序列化后的字节序列重新恢复成对象。序列化机制使得对象可以脱离程序的运行而独立存在。
一个Java对象要能序列化,必须实现一个特殊的java.io.Serializable
接口,这个接口不包含任何方法或成员变量,只是一个标记。
?
序列化通过ObjectOutputStream来实现,它可以把一个Java对象写入字节流。
当序列化一个对象到文件时, 按照 Java 的标准约定是给文件一个 .ser 扩展名.
?
示例:
import java.io.*;
public class SerializableDemo {
public static void main(String[] args) throws Exception {
File file = new File("E:\\person.ser");
FileOutputStream out = new FileOutputStream(file);
ObjectOutputStream objectOutputStream = new ObjectOutputStream(out);
Person person = new Person("王大锤", 25);
objectOutputStream.writeObject(person);
System.out.println("写入的对象:" + person);
}
private static void readObj() throws Exception{
File file = new File("E:\\person.ser");
FileInputStream in = new FileInputStream(file);
ObjectInputStream objectInputStream = new ObjectInputStream(in);
Person person = (Person)objectInputStream.readObject();
System.out.println("读取的对象:" + person);
}
}
class Person implements Serializable{
private String name;
private int age;
public Person(String name, int age) {
System.out.println("Person‘s constructor");
this.name = name;
this.age = age;
}
//...省略getter、setter、toString
}
程序输出:
Person‘s constructor
写入的对象:Person{name=‘王大锤‘, age=25}
?
反序列化使用ObjectInputStream对象,它可以从字节流中读取一个Java对象。若反序列化时要使用readObject()
读出多个对象,注意要与写入的顺序一致。
示例:
import java.io.*;
public class SerializableDemo {
public static void main(String[] args) throws Exception {
File file = new File("E:\\person.ser");
FileInputStream in = new FileInputStream(file);
ObjectInputStream objectInputStream = new ObjectInputStream(in);
Person person = (Person)objectInputStream.readObject();
System.out.println("读取的对象:" + person);
}
}
程序输出:
读取的对象:Person{name=‘王大锤‘, age=25}
可以看到反序列化时,Person的构造器并没有执行。反序列化时,是由JVM直接构造出Java对象,不调用构造方法,构造方法内部的代码,在反序列化时根本不可能执行。
?
在反序列化时readObject()
可能抛出的异常有:
ClassNotFoundException
:没有找到对应的Class;InvalidClassException
:Class不匹配。抛出ClassNotFoundException
的情况:一台电脑上的Java程序把一个Java对象序列化以后,通过网络传给另一台电脑上的另一个Java程序,但是这台电脑的Java程序并没有定义该类,所以无法反序列化,抛出该异常。
抛出InvalidClassException
的情况:例如序列化的Person
对象定义了一个int
类型的age
字段,但是反序列化时,Person
类定义的age
字段被改成了long
类型,所以导致class不兼容。为了避免这种不兼容,Java的序列化允许class定义一个特殊的serialVersionUID
静态变量,用于标识Java类的序列化“版本”。如果增加或修改了字段,可以改变serialVersionUID
的值,这样就能自动阻止不匹配的class版本。
IDEA自动生成serialVersionUID静态变量的方法:IDEA自动生成serialVersionUID
?
readObject()
读出的是同一个对象。?
示例:
示例中的Person类同上。新增了一个ID类:
package stream.serializable;
import java.io.Serializable;
public class ID implements Serializable {
private static final long serialVersionUID = -5829455553074732547L;
private int number;
private Person person;
//...省略getter、setter、toString
}
?
创建一个Person对象person和一个ID对象id,id中的Person指向person。将person和id序列化。再反序列,可看到readId.getPerson()==readPerson
返回true。
public static void main(String[] args) throws Exception {
File file = new File("E:\\id.ser");
FileOutputStream out = new FileOutputStream(file);
ObjectOutputStream objectOutputStream = new ObjectOutputStream(out);
ID id = new ID();
Person person = new Person("王大锤", 30);
id.setNumber(1);
id.setPerson(person);
objectOutputStream.writeObject(id);
objectOutputStream.writeObject(person);
FileInputStream in = new FileInputStream(file);
ObjectInputStream objectInputStream = new ObjectInputStream(in);
ID readId = (ID) objectInputStream.readObject();
Person readPerson = (Person) objectInputStream.readObject();
System.out.println(readId);
System.out.println(readPerson);
System.out.print("readId.getPerson()==readPerson:");
System.out.print(readId.getPerson()==readPerson);
}
?
《疯狂Java讲义 第4版》
---------------------------------------------------------
?
标签:static dex shu 修改 使用 vat rgs 示例 final
原文地址:https://www.cnblogs.com/bxiaoo/p/13888517.html