JAVASE序列化和反序列化讲解


在这里插入图片描述

序列化

1.序列化:Serialize java对象存储到磁盘文件中,将java对象的状态保存下来的过程
(ObjectOutputStream)(从内存到硬盘,也就是输出

2.参与序列化和反序列化对象,必须实现Serializable接口,只是一个标志接口

java中有两种接口

  1. 普通接口
  2. 标志接口(标志接口都是没有方法的)

常见问题

在这里插入图片描述
报错原因是:所需序列化的类对象并没有继承接口Serializable

在这里插入图片描述

然后按下ctrl + b可以查看这个接口Serializable源码
在这里插入图片描述

标志性接口

很显然,这是一个标志性接口

注意:通过源代码发现,Serializable接口只是一个标志接口:

  public interface Serializable{
    
    
}

那么这个接口中当中什么都没有

那么它到底起什么作用,标志的作用,java虚拟机看到这个类实现了这个接口,可能会对这个类进行特殊待遇。

Serializable这个标志接口是给java虚拟机参考的,java虚拟机看到这个接口之后,会为该类自动生成一个序列化版本号

序列化版本号有什么用?

过了很久,序列化原来那个类源代码改动了,
源代码改动了之后,需要重新编译,编译之后生成了全新的字节码文件
并且class文件再次运行的时候,java虚拟机生成的序列化版本号也会随之发生相应的改变

序列化对象

Student

import java.io.Serializable;

public class Student  {
    
    
   private int no;
   private String name;

   public  Student(){
    
    

   }

   public Student(int no ,String name ){
    
    
      this.name=name;
      this.no=no;

   }

   public int getNo() {
    
    
      return no;
   }

   public String getName() {
    
    
      return name;
   }

   public void setNo(int no) {
    
    
      this.no = no;
   }

   public void setName(String name) {
    
    
      this.name = name;
   }

   @Override
   public String toString() {
    
    
      return "Student{" +
              "no=" + no +
              ", name='" + name + '\'' +
              '}';
   }
}

main

import java.io.FileOutputStream;                                                                      
import java.io.ObjectOutputStream;                                                                    
import java.io.Serializable;                                                                          
                                                                                                      
public class ObjectOutputStreamTest01 implements Serializable {
    
                                           
    public static void main(String[] args) throws Exception{
    
                                              
        //创建java对象                                                                                    
        Student s=new Student(111,"豪哥");                                                              
                                                                                                      
        //序列化                                                                                         
        ObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream("students"));              
                                                                                                      
        //序列化对象                                                                                       
        oos.writeObject(s);                                                                           
                                                                                                      
        //刷新                                                                                          
        oos.flush();                                                                                  
                                                                                                      
        //关闭                                                                                          
        oos.close();                                                                                  
                                                                                                      
    }                                                                                                 
}                                                                                                     
                                                                                                      

实现截图

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

序列化集合

import java.io.FileOutputStream;                                                                        
import java.io.ObjectOutputStream;                                                                      
import java.util.ArrayList;                                                                             
import java.util.List;                                                                                  
                                                                                                        
public class ObjectOutputStreamTest01 {
    
                                                                     
    public static void main(String[] args) throws Exception{
    
                                                
            //创建对象list集合                                                                                              
        List<Student>userList=new ArrayList<>();                                                        
         userList.add(new Student(1,"莫老板"));                                                            
         userList.add(new Student(2,"戴总"));                                                             
         userList.add(new Student(3,"彪彪"));                                                             
                                                                                                        
                                                                                          
                                                                                                                                                         
        //序列化                                                                                           
        ObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream("students"));                
                                                                                                        
        //序列化对象                                                                                         
        oos.writeObject(userList);                                                                      
                                                                                                        
        //刷新                                                                                            
        oos.flush();                                                                                    
                                                                                                        
        //关闭                                                                                            
        oos.close();                                                                                    
                                                                                                        
    }                                                                                                   
}                                                                                                       
                                                                                                        

在这里插入图片描述

在这里插入图片描述

反序列化

反序列化:DeSerialize 将硬盘上的数据重新恢复到内存当中,恢复成java对象(ObjectInputStream)(从硬盘到内存,也就是输入

反序列化对象

import java.io.FileInputStream;
import java.io.ObjectInputStream;

public class ObjectInputStreamtTest01 {
    
    
    public static void main(String[] args) throws Exception{
    
    
        ObjectInputStream ois=new ObjectInputStream(new FileInputStream("students"));

        //开始序列化,读
        Object obj=ois.readObject();

        //反序列化回来是一个学生对象,所以会调用学生对象的toString方法
        System.out.print(obj);

        ois.close();
    }
}

在这里插入图片描述

反序列化集合

判断反序列化是否是集合

首先利用代码判断,反序列的东西,是否是集合:

import java.io.FileInputStream;
import java.io.ObjectInputStream;
import java.util.List;

public class ObjectInputStreamtTest01 {
    
    
    public static void main(String[] args) throws Exception{
    
    
        ObjectInputStream ois=new ObjectInputStream(new FileInputStream("students"));

        //开始序列化,读
        Object obj=ois.readObject();
        System.out.print(obj instanceof List);
        ois.close();
    }
}

在这里插入图片描述

反序列化集合代码

import java.io.FileInputStream;
import java.io.ObjectInputStream;
import java.util.List;

public class ObjectInputStreamtTest01 {
    
    
    public static void main(String[] args) throws Exception{
    
    
        ObjectInputStream ois=new ObjectInputStream(new FileInputStream("students"));
        
        List<Student> userList=(List<Student>) ois.readObject();

        //反序列化回来是一个学生对象,所以会调用学生对象的toString方法
       for(Student student:userList){
    
    

           System.out.print(student);
       }

        ois.close();
    }
}

在这里插入图片描述

注意

如果不用集合,直接存多个对象,那么存第二个对象会报错的,需要使用List集合

transient

transient 关键字表示游离的,不参与序列化

Student类

import java.io.Serializable;

public class Student implements Serializable  {
    
    
   private int no;
   transient private String name;

   public  Student(){
    
    

   }

   public Student(int no ,String name ){
    
    
      this.name=name;
      this.no=no;

   }

   public int getNo() {
    
    
      return no;
   }

   public String getName() {
    
    
      return name;
   }

   public void setNo(int no) {
    
    
      this.no = no;
   }

   public void setName(String name) {
    
    
      this.name = name;
   }

   @Override
   public String toString() {
    
    
      return "Student{" +
              "no=" + no +
              ", name='" + name + '\'' +
              '}';
   }
}

注意

name前面加了个transient关键字

反序列化代码

import java.io.FileInputStream;
import java.io.ObjectInputStream;
import java.util.List;

public class ObjectInputStreamtTest01 {
    
    
    public static void main(String[] args) throws Exception{
    
    
        ObjectInputStream ois=new ObjectInputStream(new FileInputStream("students"));

        List<Student> userList=(List<Student>) ois.readObject();

        //反序列化回来是一个学生对象,所以会调用学生对象的toString方法
       for(Student student:userList){
    
    

           System.out.print(student);
       }

        ois.close();
    }
}

序列化代码

import java.io.FileOutputStream;                                                                        
import java.io.ObjectOutputStream;                                                                      
import java.util.ArrayList;                                                                             
import java.util.List;                                                                                  
                                                                                                        
public class ObjectOutputStreamTest01 {
    
                                                                     
    public static void main(String[] args) throws Exception{
    
                                                
                                                                                                        
        List<Student>userList=new ArrayList<>();                                                        
         userList.add(new Student(1,"莫老板"));                                                            
         userList.add(new Student(2,"戴总"));                                                             
         userList.add(new Student(3,"彪彪"));                                                             
                                                                                                        
         //创建java对象                                                                                     
        Student s=new Student(4,"豪哥");                                                                  
                                                                                                        
        //序列化                                                                                           
        ObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream("students"));                
                                                                                                        
        //序列化对象                                                                                         
        oos.writeObject(userList);                                                                      
                                                                                                        
        //刷新                                                                                            
        oos.flush();                                                                                    
                                                                                                        
        //关闭                                                                                            
        oos.close();                                                                                    
                                                                                                        
    }                                                                                                   
}                                                                                                       
                                                                                                        

执行结果

当执行序列化后,再来执行反序列结果后:结果如下:
在这里插入图片描述

name为NULL解释:

因为开始时,设置了name是不参加序列化的,所以name并没有序列化到文件中,但是最终在反序列化时,需要new对象,new三个user对象,name没有值,然后就为默认值NULL

序列化版本号有什么用?

过了很久,序列化原来那个类源代码改动了,
源代码改动了之后,需要重新编译,编译之后生成了全新的字节码文件
并且class文件再次运行的时候,java虚拟机生成的序列化版本号也会随之发生相应的改变
在这里插入图片描述

 private static final long serialVersionUID=1L;

java语言中是采用什么机制来区分类的?

  1. 首先通过类名进行对比如果类名不一样,肯定不是同一个类
  2. 如果类名一样,再怎么进行类的区别?靠序列化版本号进行区分

举例讲解

小鹏编写了一个类:com.bjpowernode.java.bean.Student implements Serializable
小李编写了一个类:com.bjpowernode.java.bean.Student implements Serializable

对于不同的人编写了同一个类,但这两个类确实不是同一个类。这个时候序列化版本就起上了作用。对于java虚拟机来说,java虚拟机是可以区分开这两个类的,因为这两个类都实现了Serializable接口,都有默认的序列化版本号,他们的序列化版本不一样,所以区分开了(这是自动生成序列化版本号的好处)

这种自动生成序列化版本号有什么缺陷?

不能修改原来的序列化类对象的代码,只要一修改代码,那么就无法反序列化(一旦代码确定之后,不能就行后续的修改因为只要修改,必然会重新编译,此时就会生成全新的序列化版本号,这时候java虚拟机会认为这是个全新的类

IDEA自动生成序列化版本号

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
勾选之后呢,点击ok

如下操作

在这里插入图片描述
当这个类没有手动添加序列化版本时,把鼠标放在Student上,然后点击Alt+回车
在这里插入图片描述
点击第一个
在这里插入图片描述
就会自动生成一串序列化版本号

最终结论:

凡是实现了Serializable接口,建议给该类提供一个固定不变的序列化版本号。这样,以后这个类即使代码修改了,但是版本号不变,java虚拟机会认为是同一个类

猜你喜欢

转载自blog.csdn.net/CSNN2019/article/details/114338611
今日推荐