java pasd_Java对象序列化(pass)

转载自:http://www.cnblogs.com/xrq730/p/4821958.html

IO操作或网络通信无法直接处理Java对象,必须将对象以某种方式表示出来,才能被IO或网络通信识别。

序列化:将一个对象转成二进制表示的字节数组,通过保存或转移这些字节数组来持久化。

反序列化:将二进制数组转化为对象。

Java序列化之需要实现java.io.Serializable接口就可以了。

默认序列化

序列化的时候又一个serialVersionUID参数,Java序列化机制是通过在运行时判断类的serialVersionUID来验证版本一致性的。在进行反序列化的时候,Java虚拟机毁把传过来的字节流中的serialVersionUID和本地相应实体类的serialVersionUID进行比较,如果相同就认为是一致的实体类,可以进行反序列化,否则Java虚拟机毁拒绝对这个实例类进行反序列化病抛出异常。

生成serialVersionUID有两种方式:

1,默认的1L

2,根据类名/接口名/成员方法以及属性等来生成一个64位的Hash字段

如果实现了Serializable接口的实体类没有显式定义一个名为serialVersonUID,类型为long的变量时,Java序列化机制会根据编译的.class文件自动生成一个serialVersionUID, 如果.class没有变化,那么就算编译两次,serialVersionUID也不会变化。Java为用户定义了默认的序列化/反序列化方法,其实就是ObjectInputStream的defaultWriteObject() 和 defaultReadObject方法。

示例1 :

packagecom.basic;importjava.io.File;importjava.io.FileInputStream;importjava.io.FileNotFoundException;importjava.io.FileOutputStream;importjava.io.IOException;importjava.io.InputStream;importjava.io.ObjectInputStream;importjava.io.ObjectOutputStream;importjava.io.OutputStream;importjava.io.Serializable;public class SerializableTest implementsSerializable{

private static final long serialVersionUID = -4573981250507373015L;privateString str0;private transientString str1;private static String str2 = "aaa";publicSerializableTest(String str0, String str1) {this.str0 =str0;this.str1 =str1;

}publicString getStr0() {return this.str0;

}publicString getStr1() {return this.str1;

}public static void main(String[] args) throwsException {//TODO Auto-generated method stub

File file= new File("C:" + File.separator + "tool" + File.separator + "SerialTest.txt");

OutputStream os= newFileOutputStream(file);

ObjectOutputStream oos= newObjectOutputStream(os);

oos.writeObject(new SerializableTest("str0", "str1"));

oos.close();

InputStream is= newFileInputStream(file);

ObjectInputStream ois= newObjectInputStream(is);

SerializableTest so=(SerializableTest)ois.readObject();

System.out.println("str0 = " +so.getStr0());

System.out.println("str1 = " +so.getStr1());

}

}

结果:

str0 =str0

str1= null

序列化文件:

aced 0005 7372 001a 636f 6d2e 6261 7369632e5365 7269 616c 697a 6162 6c65 5465

7374 c085 f449 6236 0629 0200 014c 0004

7374 7230 7400 124c 6a61 76612f6c 616e

672f5374 7269 6e67 3b78 7074 0004 7374

7230

序列化文件分五部分:

第一部分:序列化文件头

第二部分:要序列化的类的描述

第三部分:对象中各种属性的描述

第四部分:该对象父类的信息,如果没有父类就没有这部分

第五部分:输出对象的属性项的实际值,如果属性项是一个对象,还会序列化这个对象

总结:

1,序列化之后保存的是类的信息,因为一个serialVersionUID对应一个类

2,被声明为transient的属性不会被序列化

3,被声明为static的属性不会被序列化,因为序列化保存的是对象的状态,而静态属性属于类不属于对象,所以不会序列化它。

自定义序列化过程

Java并不强求用户非要使用默认的序列化方式,用户也可以按照自己的喜好自己指定自己想要的序列化方式----只要你自己能保证序列化前后能得到想要的数据就好了。手动指定序列化方式的规则是:

进行序列化、反序列化时,虚拟机会首先试图调用对象里的writeObject和readObject方法,进行用户自定义的序列化和反序列化。如果没有这样的方法,那么默认调用的是ObjectOutputStream的defaultWriteObject以及ObjectInputStream的defaultReadObject方法。换言之,利用自定义的writeObject方法和readObject方法,用户可以自己控制序列化和反序列化的过程。

这是非常有用的。比如:

1、有些场景下,某些字段我们并不想要使用Java提供给我们的序列化方式,而是想要以自定义的方式去序列化它,比如ArrayList的elementData、HashMap的table(至于为什么在之后写这两个类的时候会解释原因),就可以通过将这些字段声明为transient,然后在writeObject和readObject中去使用自己想要的方式去序列化它们

2、因为序列化并不安全,因此有些场景下我们需要对一些敏感字段进行加密再序列化,然后再反序列化的时候按照同样的方式进行解密,就在一定程度上保证了安全性了。要这么做,就必须自己写writeObject和readObject,writeObject方法在序列化前对字段加密,readObject方法在序列化之后对字段解密

示例2:

packagecom.basic;importjava.io.File;importjava.io.FileInputStream;importjava.io.FileOutputStream;importjava.io.IOException;importjava.io.InputStream;importjava.io.ObjectInputStream;importjava.io.ObjectOutputStream;importjava.io.OutputStream;importjava.io.Serializable;public class SerializableTest implementsSerializable{private static final long serialVersionUID = -4573981250507373015L;privateString str0;private transientString str1;private static String str2 = "aaa";publicSerializableTest(String str0, String str1) {this.str0 =str0;this.str1 =str1;

}publicString getStr0() {return this.str0;

}publicString getStr1() {return this.str1;

}private void writeObject(ObjectOutputStream s) throwsIOException {

System.out.println("serializing by myself");

s.defaultWriteObject();

s.writeInt(str1.length());for (int i=0; i

s.writeChar(str1.charAt(i));

}

}private void readObject(ObjectInputStream s) throwsClassNotFoundException, IOException {

System.out.println("deserializing by myself");

s.defaultReadObject();int length =s.readInt();char[] cs = new char[length];for (int i =0; i

cs[i]=s.readChar();

}

str1= new String(cs, 0, length);

}public static void main(String[] args) throwsException {//TODO Auto-generated method stub

File file= new File("C:" + File.separator + "tool" + File.separator + "SerialTest.txt");

OutputStream os= newFileOutputStream(file);

ObjectOutputStream oos= newObjectOutputStream(os);

oos.writeObject(new SerializableTest("str0", "str1"));

oos.close();

InputStream is= newFileInputStream(file);

ObjectInputStream ois= newObjectInputStream(is);

SerializableTest so=(SerializableTest)ois.readObject();

System.out.println("str0 = " +so.getStr0());

System.out.println("str1 = " +so.getStr1());

}

}

先通过defaultWriteObject和defaultReadObject方法序列化、反序列化对象,然后在文件结尾追加需要额外序列化的内容/从文件的结尾读取额外需要读取的内容。

复杂序列化情况总结

虽然Java的序列化能够保证对象状态的持久保存,但是遇到一些对象结构复杂的情况还是比较难处理的,最后对一些复杂的对象情况作一个总结:

1、当父类继承Serializable接口时,所有子类都可以被序列化

2、子类实现了Serializable接口,父类没有,父类中的属性不能序列化(不报错,数据丢失),但是在子类中属性仍能正确序列化

3、如果序列化的属性是对象,则这个对象也必须实现Serializable接口,否则会报错

4、反序列化时,如果对象的属性有修改或删减,则修改的部分属性会丢失,但不会报错

5、反序列化时,如果serialVersionUID被修改,则反序列化时会失败

1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。
应用背景为变电站电力巡检,基于YOLO v4算法模型对常见电力巡检目标进行检测,并充分利用Ascend310提供的DVPP等硬件支持能力来完成流媒体的传输、处理等任务,并对系统性能做出一定的优化。.zip深度学习是机器学习的一个子领域,它基于人工神经网络的研究,特别是利用多层次的神经网络来进行学习和模式识别。深度学习模型能够学习数据的高层次特征,这些特征对于图像和语音识别、自然语言处理、医学图像分析等应用至关重要。以下是深度学习的一些关键概念和组成部分: 1. **神经网络(Neural Networks)**:深度学习的基础是人工神经网络,它是由多个层组成的网络结构,包括输入层、隐藏层和输出层。每个层由多个神经元组成,神经元之间通过权重连接。 2. **前馈神经网络(Feedforward Neural Networks)**:这是最常见的神经网络类型,信息从输入层流向隐藏层,最终到达输出层。 3. **卷积神经网络(Convolutional Neural Networks, CNNs)**:这种网络特别适合处理具有网格结构的数据,如图像。它们使用卷积层来提取图像的特征。 4. **循环神经网络(Recurrent Neural Networks, RNNs)**:这种网络能够处理序列数据,如时间序列或自然语言,因为它们具有记忆功能,能够捕捉数据中的时间依赖性。 5. **长短期记忆网络(Long Short-Term Memory, LSTM)**:LSTM 是一种特殊的 RNN,它能够学习长期依赖关系,非常适合复杂的序列预测任务。 6. **生成对抗网络(Generative Adversarial Networks, GANs)**:由两个网络组成,一个生成器和一个判别器,它们相互竞争,生成器生成数据,判别器评估数据的真实性。 7. **深度学习框架**:如 TensorFlow、Keras、PyTorch 等,这些框架提供了构建、训练和部署深度学习模型的工具和库。 8. **激活函数(Activation Functions)**:如 ReLU、Sigmoid、Tanh 等,它们在神经网络中用于添加非线性,使得网络能够学习复杂的函数。 9. **损失函数(Loss Functions)**:用于评估模型的预测与真实值之间的差异,常见的损失函数包括均方误差(MSE)、交叉熵(Cross-Entropy)等。 10. **优化算法(Optimization Algorithms)**:如梯度下降(Gradient Descent)、随机梯度下降(SGD)、Adam 等,用于更新网络权重,以最小化损失函数。 11. **正则化(Regularization)**:技术如 Dropout、L1/L2 正则化等,用于防止模型过拟合。 12. **迁移学习(Transfer Learning)**:利用在一个任务上训练好的模型来提高另一个相关任务的性能。 深度学习在许多领域都取得了显著的成就,但它也面临着一些挑战,如对大量数据的依赖、模型的解释性差、计算资源消耗大等。研究人员正在不断探索新的方法来解决这些问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值