Java基础巩固-关于Java序列化和反序列化

题外话:
从事IT要学习的东西太多了,有时候会比较浮躁,因为要学的东西太多但又无从下手,甚至有很多基础都还没有深入学习,这个时候应当静下心来,正所谓不忘初心,方能始终,之前一直听说过序列化,但也没有去深入一点点的了解过,这个时候,就当好好巩固下了~

java序列化

常被称为持久化,将其写入磁盘中。
对于一个存在于jvm的对象来说,内部的状态保存在内存中,当jvm停止时这些状态就丢失了,但有些时候对象的内部是需要持久保存的,对象序列化机制(object serialization)是Java语言内建的一种对象持久化方式,可以很容易的在JVM中的活动对象和字节数组(流)之间进行转换,该机制中对象可以表示为字节序列,该字节序列包括该对象的数据,有关对象的类型的信息和存储在对象中数据的类型。

数据序列化就是将对象或者数据结构转化成特定的格式,使其可在网络中传输,或者可存储在内存或者文件中。反序列化则是相反的操作,将对象从序列化数据中还原出来。而对象序列化后的数据格式可以是二进制,可以是XML,也可以是JSON等任何格式。

【整个过程在jvm独立的,在一个平台上序列化的对象可以在另外的平台反序列化】

java类序列化的条件:

1.该类必须实现 java.io.Serializable接口。
2.该类的所有属性必须是可序列化的。如果有一个属性不是可序列化的,则该属性必须注明是短暂的。如果你想知道一个 Java 标准类是否是可序列化的,请查看该类的文档。检验一个类的实例是否能序列化十分简单, 只需要查看该类有没有实现 java.io.Serializable接口。

为什么序列化

1.将结构化的对象变为无结构的字节流,存储对象在存储介质中,方便下次使用可以快捷获取,便于数据传输。
2.序列化的过程通俗讲,就是一个“freeze”的过程,它将一个对象freeze住,然后进行存储,等到再次需要的时候,再将这个对象de-freeze就可以立即使用。

jdk内置序列化

java对序列化提供了很好的支持,当一个对象实现了Serilizable接口,这个对象就可以被序列化,我们不关心其内在的原理,只需要了解这个类实现了Serilizable接口,这个类的所有属性和方法都会自动序列化。可以说Serilizable只是一个标识,实际的序列化和反序列化工作是通过java.io.ObjectOuputStream和java.io.ObjectInputStream来完成的。ObjectOutputStream的writeObject方法可以把一个Java对象写入到流中,ObjectInputStream的readObject方法可以从流中读取一个Java对象。

transient关键字

在实际开发过程中可能遇到说一个对象中的属性有些需要序列化有些则不用,比如说一个用户有些敏感信息(密码,银行卡号),为了安全考虑不需要在网络操作中被传输。
这种时候使用transient可以使对应的属性不被写入磁盘持久化。换句话说,这个对象的生命周期仅存在调用者的内存中而不被持久化在硬盘中或者网络传输。

//使用例子
package serializable;
import java.io.*;

public class TransientTest implements Serializable{
    static class UserInfo implements Serializable {
        private String name; //此处加static反序列化后仍能取到是因为static修饰的变量存在jvm内存中
        private transient String psw;//transient 只能修饰变量(属性)
        public UserInfo(String name, String psw) {
            this.name = name;
            this.psw = psw;
        }

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

    public static void main(String[] args) {
        UserInfo userInfo = new UserInfo("张三", "123456");
        System.out.println(userInfo);
        try {
            // 序列化将对象属性写入到UserInfo.txt文件中,被设置为transient的属性没有被序列
            ObjectOutputStream o = new ObjectOutputStream(new FileOutputStream("UserInfo.txt"));
            o.writeObject(userInfo);
            o.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        try {
            // 重新读取序列化内容
            ObjectInputStream in = new ObjectInputStream(new FileInputStream("UserInfo.txt"));
            UserInfo readUserInfo = (UserInfo) in.readObject();
            System.out.println(readUserInfo.toString()); //修饰transient关键字的属性打印为null
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
测试

Externalizable接口

在java中,对象的序列化可以通过两种接口实现,除了Serilizable接口,还有就是Externalizable接口。
1.若实现Serializable,则所有序列化将会自动执行。
2.若实现Externalizable,序列化的过程需手动执行,需要在writeExternal方法中进行手工指定所要序列化的变量,与是否被transient修饰无关。

import java.io.*;
/**
 * Created by LJW on 2018/5/28.
 * Externalizable接口测试
 */
public class TestExternalizable implements Externalizable {
    private transient String content = "就算被transient修饰,但如果实现的是Externalizable接口,我还是可能被序列化";
    @Override
    public void writeExternal(ObjectOutput out) throws IOException {
    }

    @Override
    public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
    }

    public static void main(String[] args) throws Exception {
        TestExternalizable et = new TestExternalizable();
        //将TestExternalizable序列化到test.txt文件中
        ObjectOutput out = new ObjectOutputStream(new FileOutputStream(
                new File("test.txt")));
        out.writeObject(et);
        //反序列化test.txt中的信息
        ObjectInput in = new ObjectInputStream(new FileInputStream(new File(
                "test.txt")));
        et = (TestExternalizable) in.readObject();
        System.out.println(et.content);//成功打印content内容而不是null,说明反序列化有取到被transient修饰的变量属性
        out.close();
        in.close();
    }
}

serialVersionUID

在查看jdk源码的时候,经常看到这种代码

private static final long serialVersionUID = 2877471301981509474L; //xxxL 

一个类如果使用了java.io.Serializable接口,在序列化到文件时会自动生成一个serialVersionUID,用于对类进行版本控制(通过判断实体类的serialVersionUID来验证版本一致性的。在进行反序列化时,JVM会把传来的字节流中的serialVersionUID与本地相应实体类的serialVersionUID进行比较,如果相同就认为是一致的,可以进行反序列化,否则就会出现序列化版本不一致InvalidCalssException的异常)

如何生成

Intellij IDEA可以自动为serializable的类生成一个serialVersionUID。

File->Preferences->Inspections->Serializationissues,将其展开后将serialzable class without "serialVersionUID"打上勾;
之后双击下class类名 ALT+ENTER即可生成随机的serialVersionUID

生成serialVersionUID

总结

  1. Java序列化就是把对象转换成字节序列,而Java反序列化就是把字节序列还原成Java对象,在java中可以通过实现Serializable和Externalizable两种接口实现序列化。
  2. 采用Java序列化与反序列化技术,一是可以实现数据的持久化,在MVC模式中很有用;二是可以对象数据的远程通信,序列化用于通信,服务端把数据序列化发送到客户端。客户端收到数据反序列化对数据操作。
  3. 序列化的好处:通过序列化可以把数据永久保存在硬盘上(通常放在文件里)
  4. transient关键字只能修饰属性,被transient修饰的属性将不会被序列化(这边的前提是实现Serializable接口,还有需注意被static修饰的属性也无法被序列化,static修饰的变量存在jvm内存中,如果反序列化后得到static修饰的属性,是从jvm取而不是反序列化后得到)。
  5. serialVersionUID主要用于反序列化的时候验证版本的一致性,常在jdk,各种jar包中使用。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,080评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,422评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,630评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,554评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,662评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,856评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,014评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,752评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,212评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,541评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,687评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,347评论 4 331
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,973评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,777评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,006评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,406评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,576评论 2 349

推荐阅读更多精彩内容