Java中序列化和反序列化以及关键字 transient

总结

序列化的场景和作用:内存对象状态持久化、网络传输、远程方法调用传输对象

实现序列化方式:Serialization序列化接口、Externalizable外部序列化接口实现writeExtenal()和readExtenal()

序列化:对象输出流ObjectOutputStream和writeObject()
反序列化:对象输入流ObjectInputStream和readObject()

serialVersionUID:序列化版本标识的 静态final变量

Transient:阻止序列化
静态变量:不能被序列化


参考:
Java中的关键字 transient
java序列化与反序列化总结

详细说明

1、序列化和反序列化的概念

把Java对象转换为字节序列的过程称为对象的序列化。
把字节序列恢复为Java对象的过程称为对象的反序列化。

2、什么情况下需要序列化

当你想把的内存中的对象状态保存到一个文件中或者数据库中时候;
当你想用套接字在网络上传送对象的时候;
当你想通过RMI(远程方法调用)传输对象的时候;

3、如何实现序列化呢、使用场景?

Java提供两种对象持久化的方式,分别序列化和外部序列化。
序列化:实现Serialization接口(位于java.lang包中);
外部序列化:实现了Externalizable接口,Externalizable接口继承自Serializable接口,实现Externalizable接口的类完全由自身来控制序列化的行为;

外部序列化与序列化的区别:

序列化是内置的API,只需要,只需要实现Serialization;
使用外部序列化时,接口必须由开发人员来实现,由于控制权交给了开发人员,在编程时有更多的灵活性,可能会提高性能。Externalizable接口提供了两个方法writeExternal()和readExternal()

对Serializable对象反序列化时,并不会调用任何构造函数 ,因此Serializable类无需默认构造函数,但是当Serializable类的父类没有实现Serializable接口时,反序列化过程会调用父类的默认构造函数,因此该父类必需有默认构造函数,否则会抛异常。

对Externalizable对象反序列化时,会先调用类的不带参数的构造方法 ,这是有别于默认反序列方式的。如果把类的不带参数的构造方法删除,或者把该构造方法的访问权限设置为private、默认或protected级别,会抛出java.io.InvalidException: no valid constructor异常,因此Externalizable对象必须有默认构造函数,而且必需是public的。

4、对象序列化和反序列化的步驟?

对象序列化包括如下步骤:  
1) 创建一个对象输出流,它可以包装一个其他类型的目标输出流,如文件输出流;  
2) 通过对象输出流的writeObject()方法写对象。

对象反序列化的步骤如下:  
1) 创建一个对象输入流,它可以包装一个其他类型的源输入流,如文件输入流;  
2) 通过对象输入流的readObject()方法读取对象。

public class 序列化测试
{
    public static void main(String[] args) throws Exception
    {
        //序列化对象
        ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("d:/objectFile.data"));
        MyObject obj1 = new MyObject("liuhongliang", 24);
        out.writeObject("hello world!");
        out.writeObject(new Date());
        out.writeObject(obj1);
        out.writeInt(54);
        out.close();
        //反序列化对象 
        ObjectInputStream in = new ObjectInputStream(new FileInputStream(("d:/objectFile.data")));
        System.out.println("obj1=" + (String) in.readObject());
        System.out.println("obj2=" + (Date) in.readObject());
        MyObject obj3 = (MyObject) in.readObject();
        System.out.println("obj3=" + obj3);
        int obj4 = in.readInt();
        System.out.println("obj4=" + obj4);
        in.close();
    }
}

//自定义可序列化类
class MyObject implements Serializable
{
    private String name;
    private int age;

    public MyObject(String name, int age)
    {
        this.name = name;
        this.age = age;
    }

    public String toString()
    {
        return "name=" + name + ", age=" + age;
    }
}

5、serialVersionUID是什么?

总结:序列化和反序列化的版本控制
凡是实现Serializable接口的类都应当有一个表示序列化版本标识符的静态变量:

private static final long serialVersionUID;

当我们的类实现了Serializable接口后,会有一个警告,告诉你需要生成一个serialVersionUID属性。这个serialVersionUID是做什么用的呢?其实这是JAVA序列化的版本控制功能。当序列化对象时会把这个属性写入,当反序列化时则会把这个属性取出,然后与JAVA类中的serialVersionUID属性值对比,如果一致,则认为是同一个版本,正常反序列化,如果不一致则认为版本不同,抛出InvalidClassException异常。

6、Transient关键字

参考:Java transient关键字使用小记

作用:就是让某些被修饰的成员属性变量不被序列化;

用途:一些敏感信息,比如银行密码账号之类的,不希望网络传输或者磁盘持久化,使用transient关键字,这个字段的生命周期仅存与调用者的内存而不会写入磁盘里持久化

注意:
Transient修饰的变量和静态变量都不能被序列化;
一旦变量被transient修饰,变量将不再是对象持久化的一部分,该变量内容在序列化后无法获得访问;

在变量声明前加上该关键字,可以阻止该变量被序列化到文件中,在被反序列化后,transient 变量的值被设为初始值,如 int 型的是 0,对象型的是 null。

例如:HashMap中的modCount变量、StringBuffer用于存储的字符数组char[] toStringCache

7、Serializable接口中有几个方法?如果没有方法的话,那么这么设计Serializable接口的目的是什么?

Serializable接口在java.lang包中,是Java序列化机制的核心组成部分。它里面没有包含任何方法,我们称这样的接口为标识接口。如果你的类实现了Serializable接口,这意味着你的类被打上了“可以进行序列化”的标签,并且也给了编译器指示,可以使用序列化机制对这个对象进行序列化处理。

8、在Java进行序列化和反序列化处理的时候,哪些方法被使用了?

这个是面试中常见的问题,主要用来考察你是否对readObject()、writeObject()、readExternal()和writeExternal()方法的使用熟悉。

Java序列化是通过java.io.ObjectOutputStream这个类来完成的。这个类是一个过滤器流,这个类完成对底层字节流的包装来进行序列化处理。

通过ObjectOutputStream.writeObject(obj)进行序列化
通过ObjectInputStream.readObject()进行反序列化。

对writeObject()方法的调用会触发Java中的序列化机制。readObject()方法用来将已经持久化的字节数据反向创建Java对象,该方法返回Object类型,需要强制转换成你需要的正确类型。

9、假设一个新的类的超类实现了Serializable接口,那么如何让这个新的子类不被序列化?

重新实现writeObject()和readObject()方法,并在方法实现中通过抛出NotSerializableException

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,236评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,867评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,715评论 0 340
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,899评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,895评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,733评论 1 283
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,085评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,722评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,025评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,696评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,816评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,447评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,057评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,009评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,254评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,204评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,561评论 2 343

推荐阅读更多精彩内容

  • JAVA序列化机制的深入研究 对象序列化的最主要的用处就是在传递,和保存对象(object)的时候,保证对象的完整...
    时待吾阅读 10,836评论 0 24
  • 一、序列化 1、序列化的作用 Java平台允许我们在内存中创建可复用的Java对象,但一般情况下,只有当JVM处于...
    慕凌峰阅读 3,955评论 0 8
  • 官方文档理解 要使类的成员变量可以序列化和反序列化,必须实现Serializable接口。任何可序列化类的子类都是...
    狮_子歌歌阅读 2,386评论 1 3
  • 一年又要过去了,眨眼的功夫…
    彩树阅读 423评论 0 0
  • 其实想想我这次感冒,主要是因为前两天妈妈“太爱”我了。 前几天妈妈总是怕我冷,就让我睡觉时把我房间的门关上,我还捂...
    k坚持阅读 543评论 1 0