zoukankan      html  css  js  c++  java
  • Java 序列化

    Java序列化与反序列化是什么?

    Java序列化是指把Java对象转换为字节序列的过程;而Java反序列化是指把字节序列恢复为Java对象的过程。

    为什么需要序列化与反序列化?

    当两个进程进行远程通信时,可以相互发送各种类型的数据,这些数据会以二进制序列的形式在网络上传送。

    当两个Java进程进行通信时,能否实现进程间的对象传送?这就需要Java序列化与反序列化了。一方面,发送方需要把这个Java对象转换为字节序列,然后在网络上传送,用的是序列化;另一方面,接收方需要从字节序列中恢复出Java对象,用的反序列化。

    说白了一是为了数据持久化,二是为了让数据能够在不同平台互相传递。

    如何实现Java序列化与反序列化?

    只要实现了Serializable或Externalizable接口的类,对象就能实现序列化。

    两者区别如下:

          1、Serializable序列化时不会调用默认的构造器,而Externalizable序列化时会调用默认构造器;


          2、Serializable:一个对象想要被序列化,那么它的类就要实现此接口,这个对象的所有属性(包括private属性、包括其引用的对象)都可以被序列化和反序列化来保存、传递。

             Externalizable:它是Serializable接口的子类,有时我们不希望序列化那么多,可以使用这个接口,实现这个接口,必须重写它的writeExternal()和readExternal()方法,然后在里面指定序列化哪些属性。

    写到这来看看关键字 transient被它修饰的属性不会被序列化,由于Externalizable对象默认时不保存对象的任何字段,所以transient关键字只能伴随Serializable使用,虽然Externalizable对象中使用transient关键字也不报错,但不起任何作用。

     1 public class Person implements Serializable{
     2 
     3     private static final long serialVersionUID = -8492851170343220032L;
     4     private transient String name;//被关键字修饰过以后就不会被序列化
     5     private int age;//会被序列化
     6 
     7     public Person() {
     8     }
     9 
    10     public String getName() {
    11         return name;
    12     }
    13 
    14     public void setName(String name) {
    15         this.name = name;
    16     }
    17 
    18     public int getAge() {
    19         return age;
    20     }
    21 
    22     public void setAge(int age) {
    23         this.age = age;
    24     }
    25 
    26 }

    要想理解transient关键字更透彻的小伙伴可以自己百度,不会百度的程序员不是好的单身狗!

    这里很多小伙伴写序列化的时候不喜欢写上序列号,也就是楼上代码的serialVersionUID,表示JVM会默认创建一个序列号,不需要自己实现,这边强调下,序列号必须写上!

    序列化ID的作用  

           楼上序列化ID起着关键的作用,它决定着是否能够成功反序列化。java的序列化机制是通过在运行时判断类的serialVersionUID来验证版本一致性的,在进行反序列化时,JVM会把传来的字节流中的serialVersionUID与本地实体类中的serialVersionUID进行比较,如果相同则认为是一致的,便可以进行反序列化,否则就会报序列化版本不一致的异常。

           当我们一个实体类中没有显示的定义一个名为serialVersionUID类型为long的变量时,Java序列化机制会根据编译时的class自动生成一个serialVersionUID作为序列化版本比较,这种情况下,只有同一次编译生成的class才会生成相同的serialVersionUID。譬如,当我们编写一个类时,随着时间的推移,我们因为需求改动,需要在本地类中添加或者修改其他的字段,这个时候再反序列化时便会出现serialVersionUID不一致,导致反序列化失败。

      虚拟机是否允许反序列化,不仅取决于类路径和功能代码是否一致,一个非常重要的一点是两个类的序列化 ID 是否一致。

    文章结尾写一个序列化的例子:

    Person实体类

     1 import java.io.Serializable;
     2 
     3 /**
     4  * Created by ht on 2017/7/31.
     5  */
     6 public class Person implements Serializable{
     7 
     8     private static final long serialVersionUID = -8492851170343220032L;
     9     private String name;
    10     private int age;
    11 
    12     public Person() {
    13     }
    14 
    15     public String getName() {
    16         return name;
    17     }
    18 
    19     public void setName(String name) {
    20         this.name = name;
    21     }
    22 
    23     public int getAge() {
    24         return age;
    25     }
    26 
    27     public void setAge(int age) {
    28         this.age = age;
    29     }

    序列化实现类

     1 import java.io.*;
     2 
     3 /**
     4  * Created by ht on 2017/7/31.
     5  */
     6 public class SerializableTest implements Serializable{
     7 
     8     public static void main(String[] args) {
     9         Person person = new Person();
    10         person.setAge(18);
    11         person.setName("shuaige");
    12         ObjectOutputStream out = null;
    13         try{
    14             out = new ObjectOutputStream(new FileOutputStream("C:/Users/ht/Desktop/Serializable.txt"));
    15             out.writeObject(person);
    16             System.out.println("序列化成功");
    17         }catch (FileNotFoundException e){
    18             e.printStackTrace();
    19         }catch (IOException e){
    20             e.printStackTrace();
    21         }finally {
    22                 try {
    23                     out.close();
    24                 } catch (IOException e) {
    25                     e.printStackTrace();
    26                 }
    27         }
    28     }
    29 
    30 }

    执行输出:

    序列化成功,同时相应路径上生成Serializable.txt文件,里面是一串字节序列

    反序列化实现类

     1 import java.io.*;
     2 
     3 /**
     4  * Created by ht on 2017/7/31.
     5  */
     6 public class DesSerializeTest {
     7 
     8     public static void main(String[] args) {
     9             Person person = null;
    10             ObjectInputStream in= null;
    11             try {
    12                 in = new ObjectInputStream(new FileInputStream("C:/Users/ht/Desktop/hello.txt"));
    13                 try {
    14                     person = (Person) in.readObject();
    15                     System.out.println("反序列化成功");
    16                     System.out.println(person.getName());
    17                     System.out.println(person.getAge());
    18                 } catch (ClassNotFoundException e) {
    19                     e.printStackTrace();
    20                 }
    21             } catch (FileNotFoundException e) {
    22                 e.printStackTrace();
    23             } catch (IOException e) {
    24                 e.printStackTrace();
    25             } finally {
    26                 try {
    27                     in.close();
    28                 } catch (IOException e) {
    29                     e.printStackTrace();
    30                 }
    31             }
    32         }
    33     }

    输出:

    反序列化成功
    shuaige
    18

  • 相关阅读:
    nvm切换node失效
    React.memo is not a function
    Path must be a string. Received true
    如何通过node读取excel文件内的数据
    js中四舍五入的方法
    为什么不推荐使用数组的includes方法---记两次includes引起的问题
    改变input复选框样式
    如何使用伪元素扩大按钮可点击区域
    简单实用的纯css按钮效果
    ie6 ie7 ie8 ie9和FireFox Chrome中css区别总结
  • 原文地址:https://www.cnblogs.com/hzzjj/p/7263009.html
Copyright © 2011-2022 走看看