java序列化

本文深入探讨了Java序列化的概念、特点及其应用场景,包括序列化的基本原理、优缺点、实现方式等,并通过实例演示了如何利用序列化进行深度克隆。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

转自:https://blog.youkuaiyun.com/it_lihongmin/article/details/77932133    

先说一下,前端时间做项目的时候,遇到一个需求就是需要定时去扫描一张表,并且将没有扫描过的数据在另一张表中进行操作,所以需要记住上一次扫描的主键ID,并且在重启服务后能不丢失。于是想到了序列化,但是没弄好,就采用了修改properties的方式(当然会有一个单利的类,对内存中的进行操作,提供效率)。


一、Java序列化

        1、Java序列化:   把对象转化为字节序列的过程称为序列化,反之称为反序列化。

        2、Java序列化的缺点:1)、结果为二进制文件,文件比较大,传输过程较长

                                                  2)、不能跨语言

        3、serialVersionUID的作用,摘要算法生成一个唯一编号(类似于下载文件的MD5加密的作用)。

        4、序列化的演进: 

              1)、由于java序列化的缺点很长一段时候都是使用xml进行对象的序列化,对语言进行兼容的同时,也比二进制的序列化容易理解。

                   即基于xml的soap协议对应的webservice很长一段时间成为标准。

              2)、json的简单文本编码格式的Http restful 接口,但是json的问题在于序列化的的空间大、性能低等。

              3)、为满足移动客户端的快速响应的体验,于是二进制协议成为热点,如:messagePack。

二、序列化的特点:

        1、序列化不保存静态变量

        2、transient:关键字修改的字段不参与序列化,则为其类型的默认值

        3、如果父类没有序列化,而子类实现序列化,则子类中的父类成员不能进行序列化

        4、序列化的存储规则:对同一对象进行多次写入,打印出的存储结果和第二次的存储结果,只是多了5个字节的引用关系,并不会累加文件。


[java] view plain copy
  1. package com.kevin.demo;  
  2.   
  3. import java.io.Serializable;  
  4.   
  5. public class Person extends ParentPerson implements Serializable{  
  6.   
  7.     /** 
  8.      *  
  9.      */  
  10.     private static final long serialVersionUID = -1410109129055379293L;  
  11.   
  12.     private static String name;   
  13.       
  14.     private String address;  
  15.       
  16.     private transient int age;  
  17.   
  18.       
  19.       
  20.     @Override  
  21.     public String toString() {  
  22.         return "Person [name=" + name + "address=" + address + ", age=" + age + "]";  
  23.     }  
  24.   
  25.     public static String getName() {  
  26.         return name;  
  27.     }  
  28.   
  29.     public static void setName(String name) {  
  30.         Person.name = name;  
  31.     }  
  32.   
  33.     public String getAddress() {  
  34.         return address;  
  35.     }  
  36.   
  37.     public void setAddress(String address) {  
  38.         this.address = address;  
  39.     }  
  40.   
  41.     public int getAge() {  
  42.         return age;  
  43.     }  
  44.   
  45.     public void setAge(int age) {  
  46.         this.age = age;  
  47.     }  
  48.       
  49.       
  50. }  

[java] view plain copy
  1. package com.kevin.demo;  
  2.   
  3. public class ParentPerson {  
  4.   
  5.     private String oldName;  
  6.   
  7.     public String getOldName() {  
  8.         return oldName;  
  9.     }  
  10.   
  11.     public void setOldName(String oldName) {  
  12.         this.oldName = oldName;  
  13.     }  
  14.       
  15.       
  16. }  

[java] view plain copy
  1. package com.kevin.demo;  
  2.   
  3. import java.io.File;  
  4. import java.io.FileInputStream;  
  5. import java.io.FileNotFoundException;  
  6. import java.io.FileOutputStream;  
  7. import java.io.IOException;  
  8. import java.io.ObjectInputStream;  
  9. import java.io.ObjectOutputStream;  
  10.   
  11. /** 
  12.  * 序列化反序列化工具类 
  13.  * (如果写工具类可以考虑写的根目录的一个特定文件夹下,包名称的子文件夹下) 
  14.  * @author kevin 
  15.  * 
  16.  */  
  17. public class SerializeUtil {  
  18.   
  19.     public static void main(String[] args) {  
  20.         // 序列化对象  
  21. //      serialize();  
  22.           
  23.         // 反序列化  
  24.         unSerialize();  
  25.     }  
  26.       
  27.     /** 
  28.      * 序列化(将对象序列化到项目的根目录下) 
  29.      */  
  30.     public static void serialize(){  
  31.         try {  
  32.             ObjectOutputStream oStream = new ObjectOutputStream(new FileOutputStream(new File("person")));  
  33.             Person person = new Person();  
  34.             person.setName("kevin");  
  35.             person.setAge(18);  
  36.             person.setOldName("old kevin");  
  37.             person.setAddress("beijing");  
  38.               
  39.             oStream.writeObject(person);  
  40.             System.out.println("序列化成功!");  
  41.               
  42.             oStream.close();  
  43.         } catch (FileNotFoundException e) {  
  44.             // TODO Auto-generated catch block  
  45.             e.printStackTrace();  
  46.         } catch (IOException e) {  
  47.             // TODO Auto-generated catch block  
  48.             e.printStackTrace();  
  49.         }  
  50.           
  51.     }  
  52.       
  53.     public static void unSerialize(){  
  54.         try {  
  55.             ObjectInputStream iStream = new ObjectInputStream(new FileInputStream(new File("person")));  
  56.             Person person = (Person)iStream.readObject();   
  57.             System.out.println("反序列化成功!");  
  58.               
  59.             System.out.println(person);  
  60.               
  61.             iStream.close();  
  62.           
  63.         } catch (ClassNotFoundException e) {  
  64.             // TODO Auto-generated catch block  
  65.             e.printStackTrace();  
  66.         } catch (FileNotFoundException e) {  
  67.             // TODO Auto-generated catch block  
  68.             e.printStackTrace();  
  69.         } catch (IOException e) {  
  70.             // TODO Auto-generated catch block  
  71.             e.printStackTrace();  
  72.         }  
  73.           
  74.     }  
  75. }  
[html] view plain copy
  1. 反序列化成功!  
  2. Person [name=nulladdress=beijing, age=0]  

三、序列化实现深度克隆

        1、浅拷贝(浅复制、浅克隆): 被复制对象的所以变量都有与原来的对象相同的值,而所有的其他对象的引用任然指向原来的对象。

        2、深拷贝(深复制、深克隆):被复对象的所有变量都含有与原来的对象相同的值,除去那些引用其他对象的变量。即深拷贝,需要将对象引用的对象一并进行拷贝。

[java] view plain copy
  1. public class Student implements Serializable{  
  2.   
  3.   
  4.     private static final long serialVersionUID = 5630895052908986144L;  
  5.   
  6.   
  7.     private String name;  
  8.   
  9.     private int age;  
  10.   
  11.   
  12.     private Teacher teacher;  
  13.   
  14.     public String getName() {  
  15.         return name;  
  16.     }  
  17.   
  18.     public void setName(String name) {  
  19.         this.name = name;  
  20.     }  
  21.   
  22.     public int getAge() {  
  23.         return age;  
  24.     }  
  25.   
  26.     public void setAge(int age) {  
  27.         this.age = age;  
  28.     }  
  29.   
  30.     public Teacher getTeacher() {  
  31.         return teacher;  
  32.     }  
  33.   
  34.     public void setTeacher(Teacher teacher) {  
  35.         this.teacher = teacher;  
  36.     }  
  37.   
  38.     public Object deepClone() throws IOException, ClassNotFoundException {  
  39.         //序列化  
  40.         ByteArrayOutputStream baos=new ByteArrayOutputStream();  
  41.         ObjectOutputStream oos=new ObjectOutputStream(baos);  
  42.   
  43.         oos.writeObject(this);  
  44.   
  45.         //反序列化  
  46.         ByteArrayInputStream bais=new ByteArrayInputStream(baos.toByteArray());  
  47.         ObjectInputStream ois=new ObjectInputStream(bais);  
  48.         return ois.readObject();  
  49.     }  
  50.   
  51.   
  52.     @Override  
  53.     public String toString() {  
  54.         return "Student{" +  
  55.                 "name='" + name + '\'' +  
  56.                 ", age=" + age +  
  57.                 ", teacher=" + teacher +  
  58.                 '}';  
  59.     }  
  60. }  

[java] view plain copy
  1. public class Teacher implements Serializable{  
  2.   
  3.     private static final long serialVersionUID = -6635991328204468281L;  
  4.     private String name;  
  5.   
  6.     public String getName() {  
  7.         return name;  
  8.     }  
  9.   
  10.     public void setName(String name) {  
  11.         this.name = name;  
  12.     }  
  13.   
  14.     @Override  
  15.     public String toString() {  
  16.         return "Teacher{" +  
  17.                 "name='" + name + '\'' +  
  18.                 '}';  
  19.     }  
  20. }  
[java] view plain copy
  1. public class CloneDemo {  
  2.   
  3.     public static void main(String[] args) throws IOException, ClassNotFoundException {  
  4.         Teacher teacher=new Teacher();  
  5.         teacher.setName("mic");  
  6.   
  7.         Student student=new Student();  
  8.         student.setName("kevin");  
  9.         student.setAge(18);  
  10.         student.setTeacher(teacher);  
  11.   
  12.         Student student2=(Student) student.deepClone(); //  
  13.         System.out.println(student);  
  14.   
  15.         student2.getTeacher().setName("james");  
  16.         System.out.println(student2);  
  17.   
  18.   
  19.     }  
  20. }  


四、主流的序列化技术及性能

     JSON、 dubbo采用的 Hessian(2) 、xml、protobuf、kryo、MsgPack、FST、thrift、protostuff、Avro

用代码简单分析一下性能问题:

[java] view plain copy
  1. public class JsonDemo {  
  2.   
  3.     //初始化  
  4.     private static Person init(){  
  5.         Person person=new Person();  
  6.         person.setName("mic");  
  7.         person.setAge(18);  
  8.         return person;  
  9.     }  
  10.   
  11.     public static void main(String[] args) throws IOException {  
  12. //        excuteWithJack();  
  13.   
  14.         excuteWithFastJson();  
  15.   
  16. //        excuteWithProtoBuf();  
  17. //  
  18. //        excuteWithHessian();  
  19.     }  
  20.   
  21.     private static void excuteWithJack() throws IOException {  
  22.         Person person=init();  
  23.   
  24.         ObjectMapper mapper=new ObjectMapper();  
  25.         byte[] writeBytes=null;  
  26.         Long start=System.currentTimeMillis();  
  27.         for(int i=0;i<10000;i++){  
  28.             writeBytes=mapper.writeValueAsBytes(person);  
  29.         }  
  30.         System.out.println("Json序列化:"+(System.currentTimeMillis()-start)+"ms : " +  
  31.                 "总大小->"+writeBytes.length);  
  32.   
  33.         Person person1=mapper.readValue(writeBytes,Person.class);  
  34.         System.out.println(person1);  
  35.     }  
  36.   
  37.   
  38.     private static void excuteWithFastJson() throws IOException {  
  39.         Person person=init();  
  40.         String text=null;  
  41.         Long start=System.currentTimeMillis();  
  42.         for(int i=0;i<10000;i++){  
  43.             text=JSON.toJSONString(person);  
  44.         }  
  45.         System.out.println("fastjson序列化:"+(System.currentTimeMillis()-start)+"ms : " +  
  46.                 "总大小->"+text.getBytes().length);  
  47.   
  48.         Person person1=JSON.parseObject(text,Person.class);  
  49.         System.out.println(person1);  
  50.     }  
  51.   
  52.     private static void excuteWithProtoBuf() throws IOException {  
  53.         Person person=init();  
  54.         Codec<Person> personCodec= ProtobufProxy.create(Person.class,false);  
  55.   
  56.         Long start=System.currentTimeMillis();  
  57.         byte[] bytes=null;  
  58.         for(int i=0;i<10000;i++){  
  59.              bytes=personCodec.encode(person);  
  60.         }  
  61.         System.out.println("protobuf序列化:"+(System.currentTimeMillis()-start)+"ms : " +  
  62.                 "总大小->"+bytes.length);  
  63.   
  64.         Person person1=personCodec.decode(bytes);  
  65.         System.out.println(person1);  
  66.     }  
  67.   
  68.     private static void excuteWithHessian() throws IOException {  
  69.         Person person=init();  
  70.   
  71.         ByteArrayOutputStream os=new ByteArrayOutputStream();  
  72.         HessianOutput ho=new HessianOutput(os);  
  73.         Long start=System.currentTimeMillis();  
  74.         for(int i=0;i<10000;i++){  
  75.             ho.writeObject(person);  
  76.             if(i==0){  
  77.                 System.out.println(os.toByteArray().length);  
  78.             }  
  79.         }  
  80.         System.out.println("Hessian序列化:"+(System.currentTimeMillis()-start)+"ms : " +  
  81.                 "总大小->"+os.toByteArray().length);  
  82.   
  83.         HessianInput hi=new HessianInput(new ByteArrayInputStream(os.toByteArray()));  
  84.         Person person1=(Person)hi.readObject();  
  85.         System.out.println(person1);  
  86.     }  
  87. }  

依赖的jar如下:
[html] view plain copy
  1. <dependencies>  
  2.         <dependency>  
  3.             <groupId>junit</groupId>  
  4.             <artifactId>junit</artifactId>  
  5.             <version>3.8.1</version>  
  6.             <scope>test</scope>  
  7.         </dependency>  
  8.         <dependency>  
  9.             <groupId>org.codehaus.jackson</groupId>  
  10.             <artifactId>jackson-mapper-asl</artifactId>  
  11.             <version>1.9.13</version>  
  12.         </dependency>  
  13.         <dependency>  
  14.             <groupId>com.alibaba</groupId>  
  15.             <artifactId>fastjson</artifactId>  
  16.             <version>1.2.31</version>  
  17.         </dependency>  
  18.         <dependency>  
  19.             <groupId>com.baidu</groupId>  
  20.             <artifactId>jprotobuf</artifactId>  
  21.             <version>2.1.2</version>  
  22.         </dependency>  
  23.         <dependency>  
  24.             <groupId>com.caucho</groupId>  
  25.             <artifactId>hessian</artifactId>  
  26.             <version>4.0.38</version>  
  27.         </dependency>  
  28.     </dependencies> 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值