`

序列化与反序列化

阅读更多

                                                         序列化与反序列化
一:序列化的原因:
    1.永久性的保存对象,保存对象的字节序列到本地文件中(做游戏是可以用来进行存档将游戏的各种属性存到本地文件中,读档的时候进行恢复);
    2.通过序列化对象在网络中传递对象;
    3.通过序列化在进程间传递对象;

二:序列化的使用:

1.实现Serializable序列化(http://www.cnblogs.com/xdp-gacl/p/3777987.html)

Person类:要序列化的类

 

import java.io.Serializable;

public class Person implements Serializable {

	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;
	}

}

 

 

 

 Test类:序列化的实现

 

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.text.MessageFormat;

public class Test {
 
     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()));
     }
     
    
    private static void SerializePerson() throws FileNotFoundException,
            IOException {
        Person person = new Person();
        person.setName("gacl");
        person.setAge(25);
        person.setSex("男");
         // ObjectOutputStream 对象输出流,将Person对象存储到Person.txt文件中,完成对Person对象的序列化操作
         File f =  new File("Person.txt");
         FileOutputStream fs = new FileOutputStream(f);
         ObjectOutputStream oo = new ObjectOutputStream(fs);
         oo.writeObject(person);
         System.out.println("Person对象序列化成功!");
         oo.close();
     }
 
     
     private static Person DeserializePerson() throws Exception, IOException {
         ObjectInputStream ois = new ObjectInputStream(new FileInputStream(
                 new File("Person.txt")));
         Person person = (Person) ois.readObject();
         System.out.println("Person对象反序列化成功!");
         return person;
     }
 
 }
 

serialVersionUID每个类只要实现了Serializable如果不定义该变量,编译器就会有警告标志,那么这个变量是做什么用的呢?其实他是用来对序列话文件进行编号,如果你不定义该变量,在你对序列化的对象进行了修改后用原来的序列化文件反序列化程序就会报异常。因为你改变对象的内容后重新编译serialVersionUID的值会改变,你根据原来的serialVersionUID的值就找不到了编译后的class,这样就造成版本冲突。意思就是说,文件流中的class和classpath中的class,也就是修改过后的class,不兼容了,处于安全机制考虑,程序抛出了错误,并且 拒绝载入。那么如果我们真的有需求要在序列化后添加一个字段或者方法呢?应该怎么办?那就是自己去指定serialVersionUID。在 TestSerialversionUID例子中,没有指定Customer类的serialVersionUID的,那么java编译器会自动给这个 class进行一个摘要算法,类似于指纹算法,只要这个文件 多一个空格,得到的UID就会截然不同的,可以保证在这么多类中,这个编号是唯一的。所以,添加了一个字段后,由于没有显指定 serialVersionUID,编译器又为我们生成了一个UID,当然和前面保存在文件中的那个不会一样了,于是就出现了2个序列化版本号不一致的错 误。因此,只要我们自己指定了serialVersionUID,就可以在序列化后,去添加一个字段,或者方法,而不会影响到后期的还原,还原后的对象照 样可以使用。

        serialVersionUID的取值是Java运行时环境根据类的内部细节自动生成的。如果对类的源代码作了修改,再重新编译,新生成的类文件的serialVersionUID的取值有可能也会发生变化。
   类的serialVersionUID的默认值完全依赖于Java编译器的实现,对于同一个类,用不同的Java编译器编译,有可能会导致不同的 serialVersionUID,也有可能相同。为了提高serialVersionUID的独立性和确定性,强烈建议在一个可序列化类中显示的定义serialVersionUID,为它赋予明确的值

显式地定义serialVersionUID有两种用途:
  1、 在某些场合,希望类的不同版本对序列化兼容,因此需要确保类的不同版本具有相同的serialVersionUID;
  2、 在某些场合,不希望类的不同版本对序列化兼容,因此需要确保类的不同版本具有不同的serialVersionUID。

 

2.Externalizable接口:

         Externalizable是Serializable的子类,很多时候程序员需要控制序列化和反序列话的过成,该接口中提供了相应的方法进行实现。




分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics