`
lapulande
  • 浏览: 219606 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Java 对象序列化与反序列化知识点汇总

阅读更多

一、两个概念,何为序列化?何为反序列化?

 

序列化:将对象转化成流的过程称为序列化。
反序列化:将流转化成对象的过程称之为反序列化。

 

二、序列化机制一般用途?

  1.需要将对象的状态保存到文件中,而后能够通过读入对象状态来重新构造对象,恢复程序状态
  2.使用套接字在网络上传送对象的程序来说,是很有用的。
  3.通过序列化在进程间传递对象。

 

三、Java对象序列化究竟保存的是什么?

Java的序列化机制只序列化对象的属性值,而不会去序列化什么所谓的方法。其实这个问题简单思考一下就可以搞清楚,方法是不带状态的,就是一些指令,指令是不需要序列化的,只要你的JVM classloader可以load到这个类,那么类方法指令自然就可以获得。序列化真正需要保存的只是:对象的类型,对象属性的类型,对象属性的值。

 

四、序列化和反序列化的操作

 

a) Java对象和java.io.Serializable接口

 

在java中要想使一个java对象可以实现序列化与反序列化,必须让该类实现java.io.Serializable接口,它并未指定要实现的方法,所以Serializable被称为"tagging interface" ,但是它仅仅"tags"它自己的对象是一个特殊的类型。任一个您希望serialize的对象都应该实现这个接口。这是必须的。否则,用到流技术时将根本不工作。例如,如果您试着去serialize 一个没有实现这个接口的对象,一个 NotSerializableException将产生。 类通过实现 java.io.Serializable 接口以启用其序列化功能。未实现此接口的类将无法使其任何状态序列化或反序列化。可序列化类的所有子类型本身都是可序列化的。序列化接口没有方法或字段,仅用于标识可序列化的语义。

java.io.Serializable接口定义如下:

public interface Serializable {
}

 

b) 序列化和反序列化

 

序列化主要依赖java.io.ObjectOutputStream类,该类对java.io.FileOutputStream进一步做了封装,这里主要使用ObjectOutputStream类的writeObject()方法实现序列化功能。

反序列化主要依赖java.io.ObjectInputStream类,这里主要使用ObjectInputStream类的readObject()方法实现序列化功能。
在序列化的时候,writeObject与 readObject之间的先后顺序。readObject将最先write的object read出来。用数据结构的术语来讲就姑且称之为先进先出吧!
在序列化时,有几点要注意的:
  1:当一个对象被序列化时,只保存对象的非静态成员变量,不能保存任何的成员方法和静态的成员变量。
  2:如果一个对象的成员变量是一个对象,那么这个对象的数据成员也会被保存。
  3:如果一个可序列化的对象包含对某个不可序列化的对象的引用,那么整个序列化操作将会失败,并且会抛出一个NotSerializableException。我们可以将这个引用标记为transient,那么对象仍然可以序列化。

 

还有我们对某个对象进行序列化时候,往往对整个对象全部序列化了,比如说对象里有些数据不希望序列化,一个方法可以用transient来标识,另一个方法我们可以在这个类里重写二个方法
  private    void  readObject(java.io.ObjectInputStream stream)
      throws  IOException, ClassNotFoundException;
  private   void  writeObject(java.io.ObjectOutputStream stream)
      throws  IOException

 

class  ObjectSerialTest
{
     public   static   void  main(String[] args)  throws  Exception
     {
        Employee e1 = new  Employee( " zhangsan " , 25 , 3000.50 );
        Employee e2 = new  Employee( " lisi " , 24 , 3200.40 );
        Employee e3 = new  Employee( " wangwu " , 27 , 3800.55 );
        
        FileOutputStream fos = new  FileOutputStream( " employee.txt " );
        ObjectOutputStream oos = new  ObjectOutputStream(fos);
        oos.writeObject(e1);
        oos.writeObject(e2);
        oos.writeObject(e3);
        oos.close();
        
        FileInputStream fis = new  FileInputStream( " employee.txt " );
        ObjectInputStream ois = new  ObjectInputStream(fis);
        Employee e;
         for ( int  i = 0 ;i < 3 ;i ++ )
         {
            e = (Employee)ois.readObject();
            System.out.println(e.name + " : " + e.age + " : " + e.salary);
        }
        ois.close();
    }
}

class  Employee  implements  Serializable
{
    String name;
     int  age;
     double  salary;
     transient  Thread t = new  Thread();
     public  Employee(String name, int  age, double  salary)
     {
         this .name = name;
         this .age = age;
         this .salary = salary;
    }
     private   void  writeObject(java.io.ObjectOutputStream oos)  throws  IOException
     {
        oos.writeInt(age);
        oos.writeUTF(name);
        System.out.println( " Write Object " );
    }
     private   void  readObject(java.io.ObjectInputStream ois)  throws  IOException
     {
        age = ois.readInt();
        name = ois.readUTF();
        System.out.println( " Read Object " );
    }

} 
 

其实还有一个接口java.io.Externalizable,它继承了Serializable接口,所以也可以通过实现它,定义readExternal和writeExternal方法来实现序列化。

ObjectOutputStream调用类的writeExternal方法对Customer对象的非transient实例变量进行序列化;

ObjectInputStream首先通过类的无参数构造函数实例化一个对象,再用readExternal方法对对象的非transient实例变量进行反序列化。

 

五、总结

如果采用默认的序列化方式,只要让一个类实现Serializable接口,其实例就可以被序列化。通常,专门为继承而设计的类应该尽量不要实现 Serializable接口,因为一旦父类实现了Serializable接口,其所有子类也都是可序列化的了。

默认的序列化方式的不足之处:

1.直接对对象的不宜对外公开的敏感数据进行序列化,这是不安全的;

2.不会检查对象的成员变量是否符合正确的约束条件,有可能被传改数据而导致运行异常;

3.需要对对象图做递归遍历,如果对象图很复杂,会消耗很多资源,设置引起Java虚拟机的堆栈溢出;

4.使类的接口被类的内部实现约束,制约类的升级与维护。

通过实现Serializable接口的private类型的writeObject()和readObject(),或是实现 Externalizable接口,并实现writeExternal()与readExternal()方法,并提供public类型的无参数构造函数 两种方式来控制序列化过程可以有效规避默认序列化方式的不足之处。

 

 

分享到:
评论

相关推荐

    java 对象的序列化与反序列化

    Java对象的序列化和反序列化是Java编程中一项...总结,Java对象的序列化和反序列化是Java编程中的基础概念,它涉及到数据持久化、网络通信等多个方面。理解并熟练运用这一技术,能够帮助开发者更有效地管理和传递数据。

    Java反序列化实战.pdf

    ### Java反序列化实战知识点详解 #### 一、反序列化概述 - **定义**:在计算机科学领域,反序列化是指将字节流或文本流等数据转换回其原始对象结构的过程。这一过程通常与序列化相对应,序列化是将对象的状态转化...

    java知识点汇总

    首先,从【标题】:“java知识点汇总” 和【描述】:“内容较杂,有java初中高级知识点,也有Java web架构及原理”来看,涉及的内容包括了Java的序列化与反序列化、IO流的基础知识、多态的概念、泛型的应用、反射...

    Java反序列化漏洞探析及其修复方法研究.pdf

    根据文章内容,可以进一步总结出以下与Java反序列化漏洞相关的知识点: - Java反序列化漏洞的背景和原理:2015年发现的一种新型信息安全高危漏洞,由于Java语言的序列化机制存在缺陷,攻击者可以利用漏洞执行远程...

    S08-SnakeYaml反序列化1

    标题 "S08-SnakeYaml反序列化1" 提到的是关于使用SnakeYaml库进行Java对象的序列化和反序列化的知识点。SnakeYaml是一个开源的库,允许在Java应用程序中处理YAML格式的数据。以下是这些知识点的详细说明: **1. ...

    详解Java 序列化与反序列化(Serialization)

    Java 序列化与反序列化(Serialization)知识点总结 Java 序列化与反序列化是 Java 语言中的一种机制,用于将对象的状态信息转化为可以存储或者传输的形式的过程。序列化(Serialization)是将对象的状态信息转化为...

    Android 序列化对象存储到sharepreference

    总结,Android序列化对象存储到SharedPreferences是一种实用技巧,它结合了Java序列化和Android的SharedPreferences机制,为开发者提供了在应用间保存简单对象的便捷方式。然而,由于SharedPreferences的局限性,...

    JAVA及Jackson反序列化漏洞.docx

    为了实现反序列化,Java对象必须实现`java.io.Serializable`接口,这是Java序列化机制的基础。 【Jackson反序列化原理】 Jackson库是Java中广泛使用的JSON处理库,它提供了高效的序列化和反序列化功能。Jackson的...

    序列化源码

    序列化是指将一个对象的状态转化为可存储或可传输的格式,而反序列化则是将这种格式恢复为原来的对象状态。这个过程使得数据可以在不同环境间无缝迁移,如从内存到磁盘,或者通过网络在不同的计算机之间传递。 标题...

    第85天:CTF夺旗-JAVA考点反编译&XXE&反序列化1

    【Java CTF夺旗:反编译、XXE与反序列化详解】 在网络安全领域,尤其是CTF(Capture The Flag)竞赛中,Java技术经常成为关键考点,涉及到的知识点包括但不限于反编译、XXE(XML External Entity)攻击、反序列化...

    java 中Spark中将对象序列化存储到hdfs

    Java 中 Spark 中将对象序列化存储到 HDFS 概述: 在 Spark 应用中,经常会遇到这样一个需求:需要将 Java 对象序列化并存储到 HDFS,尤其是利用 MLlib 计算出来的一些模型,存储到 HDFS 以便模型可以反复利用。在...

    java序列化存储读取文件.doc

    Java序列化是将Java对象的状态转换为字节序列的过程,其目的是为了保存对象状态或在网络中传输对象。Java提供了`java.io.Serializable`接口来支持对象的序列化。实现了这个接口的对象可以被序列化为一个字节流,然后...

    java客户端服务器传递对象

    "java客户端服务器传递对象"这个主题涉及到的核心知识点主要包括Java RMI(Remote Method Invocation,远程方法调用)、对象序列化以及网络通信的基本原理。下面我们将深入探讨这些概念。 1. **Java RMI**: RMI是...

    JAVA核心知识点整理.zip

    java核心知识点整理,面试很有用 Java核心知识点2.JVM JVM 是可运行 Java 代码的假想计算机 ,包括一套字节码指令集、一组寄存器、一个...5.6JAVA 序列化(创建可复用的 Java 对象) 5.7JAVA 复制 6. Spring 原理

    memcached各种序列化策略之session共享

    - **Java序列化**:Java自带的标准序列化机制,简单易用,但相对较慢且序列化后的数据较大。 4. **Memcached与Tomcat整合**:文件名中提到了Apache Tomcat,这是一款流行的Java Servlet容器。在Tomcat中配置...

    java 对象与json字符串互相转换工具类

    - **序列化/反序列化的异常**:如果对象的属性包含不可序列化的类型(如`InputStream`),或者没有默认构造函数,可能会导致转换失败。 - **字段映射**:当对象的字段名与JSON键不一致时,可以使用注解(如Jackson...

    Java面向对象考试常考简答题.docx

    本资源是Java面向对象考试常考简答题的知识点总结,适合入门Java学习面向对象的本科生。本资源涵盖了面向对象编程的基础知识,包括对象的定义和使用、static修饰的应用、final修饰的使用、重载的实现、基于抽象类和...

    SpringBoot中时间类型 序列化、反序列化、格式处理示例代码

    在SpringBoot中处理时间类型时,通常会涉及到序列化与反序列化以及时间格式的配置。序列化是将对象转换为某种格式的过程,例如将Java对象转换为JSON字符串;反序列化则是将某种格式转换回对象的过程,如将JSON字符串...

    java-集合-知识点汇总

    "Java集合知识点汇总" Java集合是Java语言中的一种数据结构,用于存储和操作数据。Java集合的知识点汇总将会涵盖Java集合的基本概念、类型、实现、操作和注意事项等方面。 Java集合的基本概念 Java集合是Java语言...

    解决Spring Boot和Feign中使用Java 8时间日期API(LocalDate等)的序列化问题

    Jackson JSON处理器默认情况下不支持Java 8时间日期API的序列化和反序列化。为了解决这个问题,我们可以使用Jackson的JavaTimeModule模块,该模块提供了对Java 8时间日期API的支持。 解决方案 第一步:添加Jackson...

Global site tag (gtag.js) - Google Analytics