今天我们来探讨一下java的序列化与反序列化。之前对此一直有概念,但是并没有真正的去测试。大家都知道,所谓的序列化就是把java代码读取到一个文件中,反序列化就是从文件中读取出对象。在网络传输过程中,我们也需要对对象进行序列化,因为一个对象是不能进行传输的。下面先上代码
package serializable;
import java.io.*;
public class SerializableTest implements Serializable {
private static final Long serialVersionUID = 1L;
private String name;
public String sex;
protected int age;
private static int id;
transient private float height;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public static int getId() {
return id;
}
public static void setId(int id) {
SerializableTest.id = id;
}
public float getHeight() {
return height;
}
public void setHeight(float height) {
this.height = height;
}
public static void main(String[] args) throws Exception {
serializable();
deSerializable();
}
/**
* 序列化
* @throws IOException
*/
private static void serializable() throws IOException {
SerializableTest serializableTest = new SerializableTest();
serializableTest.setAge(25);
serializableTest.setId(122528);
serializableTest.setName("张三");
serializableTest.setSex("男");
serializableTest.setHeight(175);
FileOutputStream fos = new FileOutputStream("serializableTest.txt");
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(serializableTest);
oos.flush();
oos.close();
}
/**
* 反序列化
* @throws Exception
*/
public static void deSerializable() throws Exception{
FileInputStream fis = new FileInputStream("serializableTest.txt");
ObjectInputStream ois = new ObjectInputStream(fis);
SerializableTest serializableTest = (SerializableTest) ois.readObject();
System.out.println("serializableTest.getAge() = " + serializableTest.getAge());
System.out.println("serializableTest.getName() = " + serializableTest.getName());
System.out.println("serializableTest.getSex() = " + serializableTest.getSex());
System.out.println("serializableTest.getHeight() = " + serializableTest.getHeight());
System.out.println("serializableTest.getId() = " + serializableTest.getId());
}
}
此类中,包括了private、public、protected、static和transient修饰的属性,我们先看下运行结果
serializableTest.getAge() = 25 serializableTest.getName() = 张三 serializableTest.getSex() = 男 serializableTest.getHeight() = 0.0 serializableTest.getId() = 122528
可以发现transient修饰的属性并没有被序列化,这也是我们所认知的。但是static修饰的属性也不应该被序列化才对,现在对象已经被我们读到文件中了,在单独执行一次反序列化方法。
public static void main(String[] args) throws Exception {
//serializable();
deSerializable();
}
执行结果如下:
serializableTest.getAge() = 25 serializableTest.getName() = 张三 serializableTest.getSex() = 男 serializableTest.getHeight() = 0.0 serializableTest.getId() = 0
现在得到的Id的值是0,也就是这个值并没有被序列化存储到文件中。
最后再说一下序列化版本号的意义。在我的理解看来,次版本号就是为了保证程序的稳定性,如果我们不声明的话,如果开始的一个对象序列化时,会为我们自动生成一个版本,如果后面我们修改了此类,那么在反序列化的时候,会发生版本不一致的问题。所以一般我们会声明成一个定值,这样就能防止上述问题。我们可以把版本代码注释掉,运行一下反序列化结果如下:
Exception in thread "main" java.io.InvalidClassException: serializable.SerializableTest; local class incompatible: stream classdesc serialVersionUID = 4564223277371155727, local class serialVersionUID = 5130976784646098676
at java.io.ObjectStreamClass.initNonProxy(ObjectStreamClass.java:699)
at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1885)
at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1751)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2042)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1573)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:431)
at serializable.SerializableTest.deSerializable(SerializableTest.java:89)
at serializable.SerializableTest.main(SerializableTest.java:60)
来源:https://www.cnblogs.com/wanghq1994/p/12144282.html