Java基础(5)-----IO_4_序列化与反序列化

标签: java  se  io  序列化

思维导图

 

Java内部用于序列化与反序列化的接口有两个,一个是Serializable ,另一个时Externalizable,这两者的区别是如果类实现了Serializable接口,序列化时就会直接写入二进制文件Externalizable继承自Serializable接口,实现了Externalizable接口的类在序列化时必须规定那些要序列化,那些不需要序列化。而且,在反序列化时,会调用类的默认的构造方法,也就是说,如果一些数据没在默认构造方法中初始化,又没被专门写入的化,这些数据就不会被反序列化。

序列化需要使用继承自InputStream和oOutputStream的ObjectInputStream,ObjectOutputStream,这两个类是修饰流。下面是个简单的小例子。,将一个对象序列化后又进行反序列化,其中涉及到了对象含有对象引用的情况,也说明了对象网的序列化会不会重复。

package IOdemo;

import java.io.*;

public class SerializableDemo {
    public static void main(String[] args){
        try {
            //文件对象
            File file = new File("e:/object");

            //输出流
            FileOutputStream fos = new FileOutputStream(file);
            ObjectOutputStream oos = new ObjectOutputStream(fos);

            //写入对象
            TestObject to1 = new TestObject("to1");
            TestObject to2 = new TestObject("to2");
            //测试对象网是否能被写入
            //若果两个对象拥有同一个对象的引用,这个引用对象不会被重复创建
            to2.setObject(to1);

            oos.writeObject(to2);

            //输出流
            FileInputStream fis = new FileInputStream(file);
            ObjectInputStream ois = new ObjectInputStream(fis);
            //读取对象时,保证虚拟机找到class文件,不然报ClassNotFoundException异常
            TestObject to = (TestObject)ois.readObject();

            System.out.println(to.name);
            System.out.println(to.object.name);

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e){
            e.printStackTrace();
        }catch (ClassNotFoundException e){
            e.printStackTrace();
        }

    }
}

//测试的对象
class TestObject implements Serializable{
    String name;
    //测试对象网是否能被序列化
    TestObject object;
    TestObject(String name){
        this.name = name;
    }

    public void setObject(TestObject object) {
        this.object = object;
    }
}

上面的小例子是默认的序列化情况,也有一些特殊的情况需要处理,比如,不想一个字段被序列化和反序列化-----使用transient关键字,transient关键字只适用于Serializable接口。怎么自定义序列化方法,又怎么在自定义的序列化方法中调用默认的序列化方法,静态字段如何序列化。 看下面的例子。

//测试的对象
class TestObject implements Serializable{
    //静态字段不会被自动序列化
    static String name;
    transient String nothing;
    
    //静态对象不会被默认序列化,所以,必须调用特殊的方法
    //静态对象的序列化方法
    public static void serializeStaticState(ObjectOutputStream oos) throws IOException{
        oos.writeUTF(name);
    }
    //静态对象的反序列化方法
    public static void deserializeStaticState(ObjectInputStream ois) throws IOException{
        name = ois.readUTF();
    }
    
    //可以自定义序列化方法
    private void writeObject(ObjectOutputStream oos) throws IOException{
        //也可在在这个方法中调用默认的序列化方法
        oos.defaultWriteObject();
        //然后进行需要自定义的序列化
        
    }
    //可以自定义反序列化方法
    private void readObject(ObjectInputStream ois) throws IOException,ClassNotFoundException{
        //也可在在这个方法中调用默认的反序列化方法
        ois.defaultReadObject();
        //然后进行需要自定义的反序列化
    }
}

 

以上是实现Serializable接口的序列化方法,可以自动的序列化,也可以手动的序列化,而实现Externalizable接口则必须进行手动的序列化。看下面的例子。

//测试的对象2
class TestObject2 implements Externalizable{
    String name;
    //Externalizable在反序列化时,只会调用默认的构造器进行初始化,也就是说,如果
    //构造函数里没有赋值,有没有在方法里写入和读取,那么字段的值反序列化后会是0或者null,false
    public TestObject2(){
        
    }
    
    //Externalizable不会自动序列化对象,必须手动序列化
    @Override
    public void writeExternal(ObjectOutput out) throws IOException {
        out.writeUTF(name);
    }

    //Externalizable不会自动反序列化对象,必须手动反序列化
    @Override
    public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
        name = in.readUTF();
    }
}

 

最后,序列化技术可以用于网络远程调用和bean的创建。

 

原文链接:加载失败,请重新获取