java对象的串行化

串行化(序列化)它是指将对象存储到介质(如文件、内在缓冲区等)中或是以二进制方式通过网络传输。之后可以通过反串行化从这些连续的字节(byte)数据重新构建一个与原始对象状态相同的对象,因此在特定情况下也可以说是得到一个副本,但并不是所有情况都这样。序列化时,transient变量和类变量(静态变量)不会被序列化。

 Java提供了自动串行化的机制,被串行化的类必须是实现java.io.Serializable接口。这是一个标志接口

下面是一个简单的自动串行化的例子:

import java.io.Serializable;

public class Employee implements Serializable{
    private String name;
    
    public Employee(String name)
    {
        this.name=name;
    }
    
    public String getName()
    {
        return name;
    }
    
    

}
public class TestSerEmployee {
    
    public static void main(String[] args)
    {
        String filename="Employee.ser";
        
        Employee emp=new Employee("kopack");
        
        try {
            FileOutputStream f=new FileOutputStream(filename);
            ObjectOutputStream oos=new ObjectOutputStream(f);
            
            oos.writeObject(emp);
            oos.close();
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

}

这个程序运行会生成一个

Employee.ser 文件,文件里面包含了对象串行化的信息。


有了这个文件,我们就可以解串行化
public class RestoreEmployee {
    public static void main(String[] args)
    {
String filename="Employee.ser";
        
        Employee emp=null;
        
         
            try {
                FileInputStream f=new FileInputStream(filename);
                ObjectInputStream ois=new ObjectInputStream(f);
                
                emp=(Employee)ois.readObject();
                 
                System.out.println("the name is  "+emp.getName());
    

                ois.close();
            } catch (FileNotFoundException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (ClassNotFoundException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }    
        
    }

}

输出:the name is  kopack

得到的emp对象跟我们保存进去的对象的信息是一样的。说明我们已经将对象的状态保存下来了

可以看到,串行化和解串行化正好相反:

FileOutputStream f=new FileOutputStream(filename);
ObjectOutputStream oos=new ObjectOutputStream(f);
   oos.writeObject(emp);

 

FileInputStream f=new FileInputStream(filename);
ObjectInputStream ois=new ObjectInputStream(f);

emp=(Employee)ois.readObject();

Java中ObjectInputStream 与 ObjectOutputStream这两个包装类可用于输入流中读取对象类数据和将对象类型的数据写入到底层输入流 。ObjectInputStream 与 ObjectOutputStream 类所读写的对象必须实现了 Serializable 接口。需要注意的是:对象中的 transient 和 static 类型的成员变量不会被读取和写入 。

 ObjectInputStream 方法  readObject()         Read an object from the ObjectInputStream. 

transient 关键字
 
 面向对象编程的长处之一是他能够处理类设计中的小差异而无需做许多工作。假设我们重新更换公司的总经理,以至于我们不希望将他的名字记录在串行化对象中,我们希望在每次启动时填写总经理的名字。这可以使用transient关键字实现。transient意味着这个字段是临时的并且没有串行化。如果可串行化对象中有一个对不可串行化的类的引用,那么就必须使用这个关键字;无论如何,只要你不想将一个字段串行化,就可以使用这个关键字。为了将Company类中的president字段改为不被串行化。我们这样声明:
private transient Employee president;
 
如果你使用这个关键字,就一定要小心。数据的解串行化会导致president字段存在,但是他未被填聪。如果你像Restorecompany对象那样引用它,会造成以下错误:
java.lang.NullPointerException
 
这说明了要小心匹配串行化过程放进流中的数据和从流中取回的数据,否则就会出错。


transient

    是java语言的关键字,变量修饰符,如果用transient声明一个实例变量,当对象存储时,它的值不需要维持。
  Java的serialization提供了一种持久化对象实例的机制。当持久化对象时,可能有一个特殊的对象数据成员,我们不想用serialization机制来保存它。为了在一个特定对象的一个域上关闭serialization,可以在这个域前加上关键字transient。当一个对象被序列化的时候,transient型变量的值不包括在序列化的表示中然而非transient型的变量是被包括进去的。

原文地址:https://www.cnblogs.com/youxin/p/2730921.html