java中序列化和反序列化

java中的序列化和反序列化

序列化是将对象状态转换为可保持或传输的格式的过程。与序列化相对的是反序列化,它将流转换为对象。这两个过程结合起来,可以轻松地存储和传输数据。

什么是序列化

  • 序列化:将java对象转换成字节流的过程。
  • 反序列化:将字节流转换成java对象的过程。

当一些数据需要在网络上传输或者持久化到文件中时,就需要对java对象进行序列化处理。如文件发送,文件上传下载。

序列化的实现:类实现serrializable接口,这个接口没有需要实现的方法 。实现Serrializable接口是为了告诉jvm这个类的对象是可以被序列化。

注意事项:

  • 某个类可以被序列化,则其子类也可以被序列化
  • 声明为 static 和 transient 的成员变量,不能被序列化。static 成员变量是描述类级别的属性,transient 表示临时数据
  • 反序列化读取序列化对象的顺序要保持一致

序列化和反序列化地实现

JDK类库提供的序列化API:

java.io.ObjectOutputStream :表示对象输出流,其中writeObject(Object obj)方法可以将给定参数的obj对象进行序列化,将转换的一连串的字节序列写到指定的目标输出流中。

java.io.ObjectInputStream : 该类表示对象输入流,该类下的readObject(Object obj)方法会从源输入流中读取字节序列,并将它反序列化为一个java对象并返回。

序列化要求:

实现序列化的类对象必须实现了Serializable类或Externalizable类才能被序列化,否则会抛出异常。

JDK类库中的序列化步骤:

第一步:创建一个输出流对象,它可以包装一个输出流对象,如:文件输出流。

ObjectOutputStream out = new ObjectOutputStream(new fileOutputStream(“E:\\Student.txt”));

第二步:通过输出流对象的writeObject()方法写对象

out.writeObject(“hello word”);

out.writeObject(“happy”)

JDK中反序列化操作:

第一步:创建文件输入流对象

ObjectInputStream ois=new ObjectInputSteam(new fileInputStream(“E:\Student.txt”))

第二步:调用readObject()方法

String obj1 = (String)in.readObject();

String obj2 = (String)in.readObject();

注意: 为了保证正确读取数据,对象输出流写入对象的顺序与对象输入流读取对象的顺序一致。

Student类序列化和反序列化演示:

1.创建一个student类并且继承serializable接口

public class Student implements Serializable {
    private static final long serialVersionUID=-6060343040263809614L;

    private String userName;
    //private transient  String password; //transient表示不参与序列化
    private   String password;
    private String age;
    private String sex;

    public Student(String userName, String password, String age, String sex) {
        this.userName = userName;
        this.password = password;
        this.age = age;
        this.sex = sex;
    }

    public static long getSerialVersionUID() {
        return serialVersionUID;
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getAge() {
        return age;
    }

    public void setAge(String age) {
        this.age = age;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }
}

2.把student类的对象序列化到txt文件(E:\\Student.txt)中,并对文件进行反序列化:

public class Test {

    public static void main(String[] args) throws IOException, ClassNotFoundException {
        //序列化

        Student student = new Student("小吴", "mima123", "23","男");
        //判断Student.text文件是否创建成功
        File file=new File("E:\\student.txt");
        if(file.exists()){
            System.out.println("该文件存在");
        }else {
            //否在创建文件
            System.out.println("新建文件");
            file.createNewFile();
              }
        try {
            //Student对象序列化过程
            FileOutputStream fos=new FileOutputStream(file);
            ObjectOutputStream oos=new ObjectOutputStream(fos);
            //调用ObjectOutoutStream 中的wirteObject()方法写对象
            oos.writeObject(student);

//            FileOutputStream fos1 = new FileOutputStream(file);
//            ObjectOutputStream oos1 = new ObjectOutputStream(fos1);
//            //调用 ObjectOutputStream 中的 writeObject() 方法 写对象
//            oos1.writeObject(student1);       //会自动执行重写的writeExternal()方法

            oos.flush();
            fos.close();
            oos.close();

            //Student对象反序列化过程
            FileInputStream fis=new FileInputStream(file);
            //创建对象输入流
            ObjectInputStream ois=new ObjectInputStream(fis);
            //读取对象
            Student student1=(Student) ois.readObject();
            System.out.println("name:"+student1.getUserName());
            System.out.println("password:"+student1.getPassword());
            System.out.println("age:"+student1.getAge());
            System.out.println("sex:"+student1.getSex());
            System.out.println(student1);
            ois.close();
            fis.close();
        }catch (ClassNotFoundException e){
            e.printStackTrace();
        }

    }
}

transient关键字

transient关键字表示有理的,被修饰的数据不能进行序列化

这里不做详细介绍,修改情况如下:

private transient  String password;      //被transient关键字修饰,不参与序列化

Externalizable接口实现序列化与反序列化

Externalizable接口继承Serializable接口,实现Externalizable接口需要实现readExternal()方法和writeExternal()方法,这两个方法是抽象方法,对应的是serializable接口的readObject()方法和writeObject()方法,可以理解为把serializable的两个方法抽象出来。Externalizable没有serializable的限制,static和transient关键字修饰的属性也能进行序列化。

具体代码实现如下:

复制对象student命名为student1,在里面重写writeExternal()方法和readExternal()方法,如下:

    @Override
    //对抽象方法进行重写
    public void writeExternal(ObjectOutput out) throws IOException {
        out.writeObject(userName);
        out.writeObject(password);
        out.writeObject(age);
        out.writeObject(sex);
    }
    @Override
    public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
        userName = (String) in.readObject();
        password = (String) in.readObject();
        age = (String) in.readObject();
       sex = (String) in.readObject();
    }

相应的测试方法里面调用这两种方法的时候,直接调用writeObject()方法和readObject()方法即可,重写的writeExternal()和readExternal()方法会自动执行。

FileOutputStream fos1 = new FileOutputStream(file1);

                ObjectOutputStream oos1 = new ObjectOutputStream(fos1);

                //调用 ObjectOutputStream 中的 writeObject() 方法 写对象

                oos1.writeObject(st);       //会自动执行重写的writeExternal()方法

FileInputStream fis1 = new FileInputStream(file1);

                //创建对象输入流

                ObjectInputStream ois1 = new ObjectInputStream(fis1);

                //读取对象

                //会自动执行readExternal()方法

                Student1 st1 = (Student1) ois1.readObject();           //会抛出异常(类找不到异常)

虽然student1类里的password属性被static或transient修饰,但依旧被序列化。

原文链接:https://blog.csdn.net/qq_62414755/article/details/125886742

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值