Java 序列化

【java】java序列化、ArrayList序列化、序列化策略 1、如果一个类想被序列化,需要实现Serializable接口。否则将抛出异常,这是因为,在序列化操作过程中会对类型进行检查,要求被序列化的类必须属于Enum、Array和Serializable类型其中的任何一种。2、在变量声明前加上该关键字,可以阻止该变量被序列化到文件中。3、在类中增加writeObject 和 readObject 方法可以实现自定义序列化策略。 阅读详情

Java 序列化


标记接口

 public interface Serializable{}

正如你看到的,序列化就是这么简单,这个简单的外观,却隐藏着巨大的知识点

什么是序列化

Java的”对象序列化”能让你将一个实现了Serializable接口的对象转换成byte流,这样日后要用这个对象时候,你就能把这些byte数据恢复出来,并据此重新构建那个对象了。

为什么要序列化

简单说就是为了保存在内存中的各种对象的状态,并且可以把保存的对象状态再读出来。虽然你可以用你自己的各种各样的方法来保存Object States,但是Java给你提供一种应该比你自己好的保存对象状态的机制,那就是序列化。

什么情况下需要序列化

  • 当你想把的内存中的对象保存到一个文件中或者数据库中时候;
  • 当你想用套接字在网络上传送对象的时候;
  • 当你想通过RMI传输对象的时候;
  • Android中通过Intent传递数据的时候;

序列化发生了什么

  • Make a FileOutputStream
FileOutputStream fs = new FileOutputStream("foo.ser");
  • Make a ObjectOutputStream
ObjectOutputStream os = new ObjectOutputStream(fs);
  • Write the object
os.writeObject(myObject1);
  • Close the ObjectOutputStream
os.close();
Foo myFoo = new Foo();
myFoo .setWidth(37);
myFoo.setHeight(70);

当通过下面的代码序列化之后,MyFoo对象中的width和Height实例变量的值(37,70)都被保存到foo.ser文件中,这样以后又可以把它从文件中读出来,重新在堆中创建原来的对象。当然保存时候不仅仅是保存对象的实例变量的值,JVM还要保存一些小量信息,比如类的类型等以便恢复原来的对象。

要想序列化对象,你必须先创建一个OutputStream,然后把它嵌进ObjectOutputStream。这时,你就能用writeObject()方法把对象写入OutputStream了。

writeObject()方法负责写入特定类的对象的状态,以便相应的 readObject()方法可以还原它。通过调用 out.defaultWriteObject 可以调用保存 Object 的字段的默认机制。该方法本身不需要涉及属于其超类或子类的状态。状态是通过使用 writeObject 方法或使用 DataOutput 支持的用于基本数据类型的方法将各个字段写入 ObjectOutputStream 来保存的。

读的时候,你得把InputStream嵌到ObjectInputStream里面,然后再调用readObject()方法。不过这样读出来的,只是一个Object的reference,因此在用之前,还得先下传。readObject() 方法负责从流中读取并还原类字段。它可以调用 in.defaultReadObject 来调用默认机制,以还原对象的非静态和非瞬态字段。  defaultReadObject()方法使用流中的信息来分配流中通过当前对象中相应命名字段保存的对象的字段。这用于处理类发展后需要添加新字段的情形。该方法本身不需要涉及属于其超类或子类的状态。状态是通过使用 writeObject 方法或使用 DataOutput 支持的用于基本数据类型的方法将各个字段写入 ObjectOutputStream 来保存的。

Demo

public class Box implements Serializable {
    private static final long serialVersionUID = -3450064362986273896L;

    private int width;
    private int height;

    public static void main(String[] args) {
        Box myBox=new Box();
        myBox.setWidth(50);
        myBox.setHeight(30);
        try {
            FileOutputStream fs=new FileOutputStream("F:\\foo.ser");
            ObjectOutputStream os=new ObjectOutputStream(fs);
            os.writeObject(myBox);
            os.close();
            FileInputStream fi=new FileInputStream("F:\\foo.ser");
            ObjectInputStream oi=new ObjectInputStream(fi);
            Box box=(Box)oi.readObject();
            oi.close();
            System.out.println(box.height+","+box.width);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public int getWidth() {
        return width;
    }
    public void setWidth(int width) {
        this.width = width;
    }
    public int getHeight() {
        return height;
    }
    public void setHeight(int height) {
        this.height = height;
    }
}

为什么有些类不会序列化

  • 安全方面的原因,比如一个对象拥有private,public等field,对于一个要传输的对象,比如写到文件,或者进行rmi传输 等等,在序列化进行传输的过程中,这个对象的private等域是不受保护的。
  • 资源分配方面的原因,比如socket,thread类,如果可以序列化,进行传输或者保存,也无法对他们进行重新的资源分配,而且,也是没有必要这样实现。

注意事项

  • 当一个对象被序列化时,只保存对象的非静态成员变量(包括声明为private的变量),不能保存任何的成员方法和静态的成员变量。
  • 如果一个对象的成员变量是一个对象,那么这个对象的数据成员也会被序列化。
  • 如果一个可序列化的对象包含对某个不可序列化的对象的引用,那么整个序列化操作将会失败,并且会抛出一个NotSerializableException。我们可以将这个引用标记为transient,那么对象仍然可以序列化。
  • 当一个父类实现序列化,子类自动实现序列化,不需要显式实现Serializable接口;
  • 当一个对象的实例变量引用其他对象,序列化该对象时也把引用对象进行序列化;

serialVersionUID

序列化运行时使用一个称为 serialVersionUID 的版本号与每个可序列化类相关联,该序列号在反序列化过程中用于验证序列化对象的发送者和接收者是否为该对象加载了与序列化兼容的类。如果接收者加载的该对象的类的 serialVersionUID 与对应的发送者的类的版本号不同,则反序列化将会导致 InvalidClassException。可序列化类可以通过声明名为 “serialVersionUID” 的字段(该字段必须是静态 (static)、最终 (final) 的 long 型字段)显式声明其自己的 serialVersionUID:

 ANY-ACCESS-MODIFIER static final long serialVersionUID = 42L;

如果可序列化类未显式声明 serialVersionUID,则序列化运行时将基于该类的各个方面计算该类的默认 serialVersionUID 值,如“Java(TM) 对象序列化规范”中所述。不过,强烈建议 所有可序列化类都显式声明 serialVersionUID 值,原因是计算默认的 serialVersionUID 对类的详细信息具有较高的敏感性,根据编译器实现的不同可能千差万别,这样在反序列化过程中可能会导致意外的 InvalidClassException。因此,为保证 serialVersionUID 值跨不同 java 编译器实现的一致性,序列化类必须声明一个明确的 serialVersionUID 值。还强烈建议使用 private 修饰符显示声明 serialVersionUID(如果可能),原因是这种声明仅应用于直接声明类 – serialVersionUID 字段作为继承成员没有用处。数组类不能声明一个明确的 serialVersionUID,因此它们总是具有默认的计算值,但是数组类没有匹配 serialVersionUID 值的要求。

此篇博文参考并修改自:http://www.cnblogs.com/gw811/archive/2012/10/10/2718331.html

(篇八)C语言在母串删子串、输入位置截取子串 文章目录一、字符串二、删除指定的字符三、从母串中截取子串四、输入位置截取子串 本篇主要介绍C语言字符串中的相关操作,然后分析两个C语言实例——在母串中指定删除子串、在母串中截取子串 一、字符串 了解C 语言的都知道,C语言中没有字符串类型,所以C语言是用字符串常量、字符指针、字符数组来表示字符串。这些字符串都是以 NULL、’\0’或者ASCII==0来结尾。说白了就是一个个字符组成一串有序序列,... 阅读详情

相关推荐

华为私有云HCS 8.1.1实战:从镜像制作到云主机发放全流程指南

本文详细解析了华为私有云HCS 8.1.1从镜像制作到云主机发放的全流程实战指南。内容涵盖制作标准化QCOW2镜像、配置云主机规格与主机组、规划外部网络,以及在运营面为租户初始化资源、配置审批流与产品目录。最后,通过用户视角演示了从创建VPC网络到申请、审批并最终绑定EIP访问云主机的完整操作步骤,为运维人员和架构师提供了一套清晰、可落地的HCS部署与管理实践方案。

weixin_29305313的博客 1128

mfc获取计算机名和用户名

两个函数搞定GetComputerName();和GetUserName();函数原型:BOOL WINAPI GetComputerName( __out LPTSTR lpBuffer, __inout LPDWORD lpnSize );BOOL WINAPI GetUserName( __out LPTSTR lpBuffer, __inout LPDWOR...

西北攻城狮的博客 3241

Mit6.S081-实验1-Xv6 and Unix utilities

Mit6.S081-实验1-Xv6 and Unix utilities前言一、Boot xv61,实验目的2,操作流程1)切换到xv6-labs-2020代码库的lab1分支2)启动xv63)测试xv64)过程分析5)其他操作二、在xv6中添加一个自己编写的程序1,源码准备2,编译配置3,测试添加程序4,过程分析三、xv6中shell简析 前言 一、Boot xv6 1,实验目的 利用qemu启动xv6 2,操作流程 1)切换到xv6-labs-2020代码库的lab1分支 git checkout ut

code a better life~ 36万+

WindowsAPI使用详解——GetComputerName|GetUserName 获取电脑名称和当前用户名

WindowsAPI使用详解——GetComputerName|GetUserName 获取电脑名称和当前用户名 - [VC++编程]版权声明:转载时请以超链接形式标明文章原始出处和作者信息及本声明http://flyxxtt.blogbus.com/logs/42725959.html获取电脑的名称,下面是函数的原: BOOL GetComputerName(LPWSTR lpBuffer,

咖啡屋 1万+

方差迭代计算公式

方差迭代计算过程推导术语约定递推公式过程推导 术语约定 (1)En=1n∑i=1nxi E_n =\frac{1}{n} \sum_{i=1}^{n}x_i \tag{1} En​=n1​i=1∑n​xi​(1) (2)F(n)=∑i=1n(x2−En) F(n) = \sum_{i=1}^{n}{(x^2-E_n)} \tag{2} F(n)=i=1∑n​(x2−En​)(2) (3)V(n)...

weixin_44479136的博客 7921

【超详细】磁力计数据读取--以IST8310为例

第一章讲了IST8310的特性,I2C通信,最高支持400kHz通信速率,14位或者16位自适应数据输出等特性第二章讲了内部结构第三章讲了电气特性第四章讲了如何联系他们然后数据手册就没了。。。在大疆的开发手册中找到了寄存器的手册,如下:点开I2C配置选项, 下图是配好的:观察IST8310的数据手册,发现其支持最大400kHz的I2C通信速率,也就是快速I2C模式,所以第一行I2C Speed Mode我们选Fast Mode同时不要忘记了在C板中I2C3的两个IO口分别是PA8和PC9(一般来说都是这两个

lmh_12138的博客 1万+

Windows API一日一练(72)GetUserName函数

随着系统安全性的加强,每个系统里越来越多不同的帐号登录。假如你正在开发一个上网安全软件,让不同的用户有不同的上网权限,这样就需要识别当前的用户是什么帐号登录了,然后再作出权限分配。还有出错时,也需要对当前帐号进行记录下来,因为不同的帐号有不同的权限,有些磁盘是不允许操作的。面对这些需求,就需要使用函数GetUserName。 函数GetUserName声明如下: WINA...

anjichan4261的博客 464

LabVIEW与三菱PLC通讯实战:ActiveX控件在FX5U上的应用技巧

本文深入探讨了如何利用三菱MX Component中的ActiveX控件,在LabVIEW中实现与FX5U系列PLC的高效、稳定通讯。文章从环境配置、ActiveX控件生命周期管理、数据读写性能优化及容错机制等实战角度,分享了构建工业级健壮通讯程序的核心技巧与架构设计思路。

qsc9012345的博客 889

VC 得到计算机名和用户名 GetComputerName GetUserName

VC 得到计算机名和用户名 GetComputerName GetUserName

weixin_43417960的博客 675

立创EDA开源项目:小北极冰冰杯(夏)——基于ESP32-C3的智能半导体制冷杯硬件设计与功能解析

本文详细解析了基于ESP32-C3的智能半导体制冷杯——小北极冰冰杯的硬件设计与核心功能。项目利用半导体制冷片实现快速降温,并集成了PWM智能调速散热、四路温度监控、杯具检测及PD/DC双电源输入等实用功能。文章深入剖析了其硬件架构、控制逻辑及实战注意事项,为嵌入式开发与智能硬件爱好者提供了宝贵的参考。

weixin_33245447的博客 271

SAP 与 Palantir 合作全景解析:这不是普通集成,而是把 ERP、数据语义层、云迁移与企业级 AI 串成一条价值链

SAP与Palantir的战略合作聚焦企业数字化转型核心痛点,通过深度技术整合构建"数据-决策-执行"闭环。合作包含四大主线:云迁移连续性保障、SAP业务数据云与Palantir平台对接、联合工程开发、高监管行业优先落地。技术实现上采用SAP认证插件,支持双向数据交互和实时业务动作触发。该合作突破了传统ERP系统局限,将业务语义与AI执行相结合,特别适合制造业供应链优化、财务争议处理等高价值场景,为企业在云迁移过程中实现业务连续性与智能化升级提供新范式。

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 192

C++ GetUserName()

关于函数“GetUserName()”,参见:https://msdn.microsoft.com/en-us/library/windows/desktop/ms724432(v=vs.85).aspx IDE: Code::Blocks 操作系统:Windows 7 x64 1 #include <windows.h> 2 #include <stdio...

weixin_34288121的博客 1276

DeepCAD: 使用深度自监督学习技术在Python中进行钙成像去噪的全面指南

钙成像是一种用于观察神经活动的技术,通过检测细胞内钙离子的变化来推断神经元的活动。由于其高时空分辨率和对活体组织的适应性,钙成像已经成为神经科学研究中的重要工具。然而,钙成像数据往往伴随着各种噪声,这些噪声可能来自于设备、生物样本或环境。为了获得准确的神经活动信息,去噪是非常关键的。深度自监督学习是一种使用未标记数据进行训练的机器学习方法。与传统的监督学习不同,它不需要大量的标记数据,而是通过学习数据的内部结构和模式来提取有用的特征。DeepCAD是一个基于深度自监督学习的钙成像去噪工具。

qq_38334677的博客 757

java之序列化与反序列化

序列化与反序列化的理解

m0_73866527的博客 1683

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

Java中的序列化及序列化ID

参考转载自: 秒懂Java序列化与反序列化 Java的序列化ID的作用 1. 定义 Java的序列化:是指把Java对象转换为字节序列的过程 Java的反序列化:是指把字节序列恢复为Java对象的过程 2. 为什么需要 我们知道,当两个进程进行远程通信时,可以相互发送各种类型的数据,包括文本、图片、音频、视频等, 而这些数据都会以二进制序列的形式在网络上传送。那么当两个Java进程进行通信时,能否实现进程间的对象传送呢?答案是可以的。如何做到呢?这就需要Java序列化与反序列化了。换句话说,一方面,.

三明治文鱼的博客 5841

IMSL CNL 7.0.0 (x86-64)Crack

IMSL CNL 7.0.0 (x86-64)Crack intel的算法库破解文件,这是C++版本的破解文件

【Java】Java序列化和反序列化

为了序列化对象,我们调用ObjectOutputStream类的writeObject()方法,而为了反序列化,则调用ObjectInputStream类的readObject()方法。SerializeISA类已序列化扩展了Person类的Student类对象,而Person类是可序列化的。序列化和反序列化过程是平台无关的,这意味着您可以在一个平台上对对象进行序列化,在另一个平台上进行反序列化。现在,id将不会序列化,因此在序列化之后反序列化对象时,您将不会得到id的值。它是序列化的逆操作。

double222222的博客 1142

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

什么是Java序列化,如何实现java序列化

序列化解释: 序列化就是一种用来处理对象流的机制,所谓对象流也就是将对象的内容进行流化。可以对流化后的对象进行读写操作,也可将流化后的对象传输于网络之间。   序列化是为了解决在对对象流进行读写操作时所引发的问题。序列化的实现:将需要被序列化的类实现Serializable接口,该接口没有需要实现的方法,implements Serializable只是为了标注该对象是可被序列化的, 然后使用一个输出流(如:FileOutputStream)来构造一个ObjectOutputStream(...

qq_38087131的博客 652

从Java序列化到Hadoop序列化

一个原生的类讲解一下,自定义比较器讲解一下,内部类讲解一下。WritableComparator是 WritableComparables的比较器。这个基础实现类使用是自然的排序规则,如果要使用其他的排序规则,需要重写compare(WritableComparable,WritableComparable)方法。

Jenny19992018的博客 591

什么是java序列化,如何实现java序列化?

序列化:将 Java 对象转换成字节流的过程。 反序列化:将字节流转换成 Java 对象的过程。 当Java 对象需要在网络上传输 或者 持久化存储到文件中时,就需要对 Java 对象进行序列化处理。 序列化的实现:类实现 Serializable 接口,这个接口没有需要实现的方法。实现 Serializable 接口是为了告诉 jvm 这个类的对象可以被序列化。 注意事项: 某个类可...

sinat_35566306的博客 672

java序列化

含义、意义使用场景 序列化:将对象写入到IO流中 反序列化:从IO流中恢复对象 意义:序列化机制允许将实现序列化的Java对象转换位字节序列,这些字节序列可以保存在磁盘上,或通过网络传输,以达到以后恢复成原来的对象。序列化机制使得对象可以脱离程序的运行而独立存在。 使用场景:所有可在网络上传输的对象都必须是可序列化的,比如RMI(remote method invoke,即远程方法调用),传入的参数或返回的对象都是可序列化的,否则会出错;所有需要保存到磁盘的java对象都必须是可序列化的。通常建议:

栋幺栋幺-的博客 1920

Java序列化与反序列化

*序列化(Serialization)**是将对象的状态信息转换为可以存储或传输的形式的过程。在Java中,序列化是将对象转换为字节序列的过程。**反序列化(Deserialization)**是将序列化的字节序列恢复为对象的过程。序列化:对象 → 字节流反序列化:字节流 → 对象通过实现和readObject// 不序列化密码// 自定义序列化// 调用默认序列化// 对密码进行加密后再序列化// 自定义反序列化// 调用默认反序列化// 解密密码。

weixin_74417835的博客 1378

java序列化指的是什么,java的序列化是什么

序列化:指堆内存中的java对象数据,通过某种方式把对存储到磁盘文件中,或者传递给其他网络节点(网络传输)。这个过程称为序列化,通常是指将数据结构或对象转化成二进制的过程。 (推荐学习:java课程)即将对象转化为二进制,用于保存,或者网络传输。序列化的作用① 想把内存中的对象保存到一个文件中或者数据库中时候;② 想用套接字在网络上传送对象的时候;③ 想通过RMI传输...

weixin_39820226的博客 2019
上一篇: JavaScript 闭包初步
下一篇: Java 并发编程框架(二)
linroidh
博客等级 码龄16年 15粉丝 35原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值