OBJECT STREAMS – SERIALIZATION AND DESERIALIZATION IN JAVA EXAMPLE USING SERIALIZABLE INTERFACE

Hitesh Garg | November 7, 2014 | io | 9 Comments

In the previous java tutorials I have discussed about basic of java streamsbyte streams, then a modified version of them character streams which were specially for character data, then data streams to solve the problem of reading and writing java primitives directly but Object Streams are used to save the state to an object by converting it into a stream and storing into a file, database or some other location(known as Serialization) and to use it at a later point of time for retrieving the stored values and restoring the objects old state( known as Deserialization).

序列化:基于对象流,将对象状态(实例变量)转换为流,并存储到文件、数据库或其他地方。

反序列化;将对象流还原,获取存储对象实例和对象状态。

TABLE OF CONTENTS –

  1. REAL LIFE CASES
  2. MARKER INTERFACE
  3. MAIN INTERFACES FOR OBJECT STREAMS
  4. MAIN CLASSES FOR OBJECT STREAMS
  5. TRANSIENT KEYWORD
  6. EXAMPLE OF SERIALIZABLE INTERFACE

This serialization and deserialization helps us in many scenarios like gaming, session state management etc.

序列化和反序列化的一些应用场景:游戏、Session状态管理等。

Have you ever wondered how a game starts from the same point where we have left it? Then this is your answer. All this is done by saving the current state of the object(or game) and reloading the state so that the player could continue from the old state only. Also the checkpoint system in games follow this method by permanently saving the progress up to that state for later use.


Serialization-deserialization in Java – Object Streams
MARKER INTERFACE(四大常用的标记接口)

An interface in Java without any field and method is a Marker interface. It is used to inform compiler that the class implementing it has some special behavior or meaning. Some of the Marker interfaces are-

  • java.io.Serializable
  • java.rmi.Remote
  • java.util.RandomAccess
  • java.lang.Cloneable

Although since Java 5 marker interfaces are replaced by annotations and they serve the same purpose as marker interfaces did before but for serializability we still use the interfaces and the transient keyword.

特别指出,标记接口中的RandomAccess的重要应用,可以参考【RandomAccess接口理解】https://blog.csdn.net/stick2it/article/details/53469910。该文章介绍了RandomAccess在Collections类的 public static <T> int binarySearch(List<? extends Comparable<? super T>> list, T key) 方法中应用。

INTERFACES

Every Object Stream class implements either of the two interfaces-

  1. OBJECTINPUT – SUBINTERFACE OF DATAINPUT
  2. OBJECTOUTPUT – SUBINTERFACE OF DATAOUTPUT

Note:- Since both the interfaces above are sub interface of interfaces Data streams interfaces, That means that all the primitive data I/O methods covered in Data Streams are also implemented in object streams.


CLASSES FOR OBJECT STREAMS

Two classes that are used for Object Streams are –

  1. OBJECTINPUTSTREAM (用于反序列化)
    • This Java class is responsible for deserializing the previously serialized objects and the primitive data. 可反序列化之前已被序列化的对象、原始类型数据。
    • It reads the object from the graph of objects stored while using FileInputStream.
    • Method readObject() is the main method used to deserialize the object.The class of the object, the signature of the class, and the values of the non-transient and non-static fields of the class and all of its super types are read. 注意非transient和非static字段才可反序列化,另外可以读取对象、类以及超类信息。
      • public final Object readObject() throws IOException,ClassNotFoundException
  2. OBJECTOUTPUTSTREAM
    • This Java class is used to store primitives and a graph of Java object which are available to ObjectInputStream to read data from.
    • This does not care about saving the super class and sub class data but it could be achieved by using the writeObject method or by using the methods for primitive data types supported by DataOutput.
    • Method writeObject() is a main method of this Java class which serializes the object directly.
      • public final void writeObject(Object obj) throws IOException

TRANSIENT KEYWORD

There are scenarios in which we want to store only a part of the object i.e. we want to omit some specific fields from the stored object just like password field from any user class or an Employee or you can think of any other sensitive information.

In these cases we mark these fields as transient and this keyword protects the field from being saved during the process of serialization.

Example – transient private String password;

transient关键词用于屏蔽那些不想被序列化的字段。


SERIALIZATION AND DESERIALIZATION EXAMPLE

Now lets take an example and see how to do this using actual Java coding and have a look at some key points that should be remembered while using Serializable interface.

USER.JAVA
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
package com.codingeek.serialization;
 
import java.io.Serializable;
 
public class User implements Serializable {
 
    /**
     * Generated Serial version Id
     */
    private static final long serialVersionUID = -55857686305273843L;
 
    private String name;
    private String username;
    transient private String password;
 
    @Override
    public String toString() {
        // TODO Auto-generated method stub
        String value = "name : " + name + "\nUserName : " + username
                + "\nPassword : " + password;
        return value;
    }
 
    /**
     * Setters and getters methods.
     */
 
    public String getName() {
        return name;
    }
 
    public void setName(String name) {
        this.name = name;
    }
 
    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;
    }
}
  • Make sure that the Java class you need to store must implement Serializable interface.
  • Notice that password field in the above class is made transient because it is a sensitive information and we don’t want to store it or you can chose any other field.
  • Also there is another field named serialVersionUID which is a Long variable and it should be defined for all the Java classes because if it is not and if in future we need to perform any changes in the class like variables, methods etc then we would never be able to deserialize an already serialized object.
    You can try it yourself by first serializing the object and then do some changes in your java class before deserializing it. You will get an error stating the change in SerialVersionUID which is generated automatically by the compiler.
  • Java的序列化机制是通过判断类的serialVersionUID来验证版本一致性的。在进行反序列化时,JVM会把传来的字节流中的serialVersionUID与本地相应实体类的serialVersionUID进行比较,如果相同就认为是一致的,可以进行反序列化,否则就会出现序列化版本不一致的异常。参考资料【3】java类中serialversionuid 作用 是什么?举个例子说明 https://www.cnblogs.com/duanxz/p/3511695.html 中有详细说明,示意图如下:


SERIALIZATIONUTIL.JAVA
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
package com.codingeek.serialization;
 
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
 
/**
 * This class is a utility class for performing the serialization and
 * deserialization operations provided the required information.
 *
 * @author hiteshgarg
 */
public class SerializationUtil {
 
    /**
     * deserialize to Object from given file. We use the general Object so as
     * that it can work for any Java Class.
     */
    public static Object deserialize(String fileName) throws IOException,
            ClassNotFoundException {
        FileInputStream fis = new FileInputStream(fileName);
        BufferedInputStream bis = new BufferedInputStream(fis);
        ObjectInputStream ois = new ObjectInputStream(bis);
        Object obj = ois.readObject();
        ois.close();
        return obj;
    }
 
    /**
     * serialize the given object and save it to given file
     */
    public static void serialize(Object obj, String fileName)
            throws IOException {
        FileOutputStream fos = new FileOutputStream(fileName);
        BufferedOutputStream bos = new BufferedOutputStream(fos);
        ObjectOutputStream oos = new ObjectOutputStream(bos);
        oos.writeObject(obj);
        oos.close();
    }
}

In the above Java utility class we have used

  • File Streams(For file related operations) which are wrapped in
  • Buffered Streams(for Speeding up the operations) which are finally wrapped into
  • Object Streams(for serialization and deserialization operations).
SERIALIZATIONTEST.JAVA
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
package com.codingeek.serialization;
import java.io.IOException;
 
public class SerializationTest {
 
    public static void main(String[] args) {
        User user = new User();
        user.setName("Hitesh");
        user.setUsername("Codingeek");
        user.setPassword("Garg");
 
        try {
            /**
             *  Serializing the object
             */
            SerializationUtil.serialize(user, "serialization.txt");
 
            /**
             * Deserializing the object
             */
            User newUser = (User) SerializationUtil.deserialize("serialization.txt");
            System.out.println(newUser.toString());
 
        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}
Output:-
name : Hitesh
UserName : Codingeek
Password : null

Notice that the password value is null and it is because we have made it a transient field and hence it was not stored and at the time of deserialization a default value is assigned to this variable( which is obviously null).

Please comment to share your views, suggestions and to report any modification if required.

KEEP LEARNING. HAPPY LEARNING 


参考资料:
【1】OBJECT STREAMS – SERIALIZATION AND DESERIALIZATION IN JAVA EXAMPLE USING SERIALIZABLE INTERFACE
【2】RandomAccess接口理解
【3】java类中serialversionuid 作用 是什么?举个例子说明




使用Serializable接口进行JAVA的序列化和反序列化的更多相关文章

  1. java 对象序列化与反序列化

    Java序列化与反序列化是什么? 为什么需要序列化与反序列化? 如何实现Java序列化与反序列化? 本文围绕这些问题进行了探讨. 1.Java序列化与反序列化  Java序列化是指把Java对象转换为 ...

  2. java对象序列化、反序列化

    平时我们在Java内存中的对象,是无法进行IO操作或者网络通信的,因为在进行IO操作或者网络通信的时候,人家根本不知道内存中的对象是个什么东西,因此必须将对象以某种方式表示出来,即存储对象中的状态.一 ...

  3. Java之序列化和反序列化

    序列化的对象: package test_demo.SerializableOper; import java.io.Serializable; /* * 序列化对象需要实现序列号接口 * */ pu ...

  4. Java基础—序列化与反序列化(转载)

    转载自: Java序列化与反序列化 1.Java序列化与反序列化 Java序列化是指把Java对象转换为字节序列的过程:而Java反序列化是指把字节序列恢复为Java对象的过程. 2.为什么需要序列化 ...

  5. Java 中序列化与反序列化

    一. 序列化和反序列化概念 Serialization(序列化)是一种将对象以一连串的字节描述的过程:反序列化deserialization是一种将这些字节重建成一个对象的过程.将程序中的对象,放入文 ...

  6. Java对象序列化和反序列化的工具方法

    import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import ja ...

  7. java之序列化与反序列化

    1.这里主要是介绍Protobuf提供的序列化与反序列化的高效性.相对于传统的java提供的序列化来说,Protobuf的效率提高了很多倍.但是也有不足的地方,就是proto在对象序列化的时候抛弃了很 ...

  8. Java 自定义序列化、反序列化

    1.如果某个成员变量是敏感信息,不希望序列化到文件/网络节点中,比如说银行密码,或者该成员变量所属的类是不可序列化的, 可以用 transient 关键字修饰此成员变量,序列化时会忽略此成员变量. c ...

  9. Java对象序列化与反序列化一 JSON

    Java对象序列化与反序列化一 JSON 1. 依赖库 jackson-all-1.6.1.jar 2. 代码 public class Student {    private String nam ...

随机推荐

  1. string类的常用功能演示

    这个程序可用随着我对string的用法的增多而有调整. /* 功能说明: string类的常用功能演示. 实现方式: 主要是演示string的常用函数的用法和它与字符数组的区别与联系 限制条件或者存在 ...

  2. bzoj 2013: A huge tower 数学

    题目: 有\(N(2\leq N\leq 620000)\)块砖,要搭一个\(N\)层的塔,要求:如果砖\(A\)在砖\(B\)上面,那么\(A\)不能比\(B\)的长度\(+D\)要长.问有几种方法 ...

  3. 五、python沉淀之路--字典

    一. 1.根据序列,创建字典,并指定统一的值 v = dict.fromkeys(["],222) print(v) {': 222} 2.根据key 获取值,key不存在时,报错:get方 ...

  4. 执行.class文件

    java packageName.className即可 但是注意,如果是有包的,这段指令一定是packageName的上层目录(即bin目录)执行!

  5. Python 函数之装饰器

    1.函数 #### 第一波 #### def foo(): print 'foo' foo #表示是函数 foo() #表示执行foo函数 #### 第二波 #### def foo(): print ...

  6. Linux网络编程——I/O复用之poll函数

    一.回顾前面的select select优点: 目前几乎在所有的平台上支持,其良好跨平台支持也是它的一个优点 select缺点: 1.每次调用 select(),都需要把 fd 集合从用户态拷贝到内核 ...

  7. check: 获得所有呗选中的checked标签的元素值 mapArrayElement(arrEles)

    首先引用: <script src="../js/myjs/mapArrayElement.js"></script> 然后在<javascript& ...

  8. [C++] 贪心算法之活动安排、背包问题

    一.贪心算法的基本思想 在求解过程中,依据某种贪心标准,从问题的初始状态出发,直接去求每一步的最优解,通过若干次的贪心选择,最终得出整个问题的最优解. 从贪心算法的定义可以看出,贪心算法不是从整体上考 ...

  9. 【转】 Pro Android学习笔记(八九):了解Handler(3):延迟执行小例子

    目录(?)[-] 小例子 Handler的处理 Activity的代码片段 后台线程和UI的互动 文章转载只能用于非商业性质,且不能带有虚拟货币.积分.注册等附加条件.转载须注明出处:http://b ...

  10. 找不到引用microsoft.office.core解决办法 via mrcjiong

    在控制面板中,选择"添加删除程序",找到office ,选择"更改",在对话框中选择"添加删除功能",然后选择自定义安装,添加上office ...