- 浏览: 235558 次
- 性别:
- 来自: 上海
文章分类
- 全部博客 (101)
- js (10)
- java (39)
- HTTP请求:GET与POST方法的区别(转) (1)
- Freemarker 语法规则 (1)
- AJAX级联菜单实例 (1)
- oralce (1)
- myeclipse (5)
- struts (12)
- sql存储过程基础(转) (4)
- JBPM (1)
- mysql (4)
- hibernate (3)
- ibatis (4)
- spring (4)
- 计算机技术 (1)
- nosql (1)
- sqlserver (1)
- servlet (1)
- 拦截器 (1)
- andriod 开发 (1)
- 程序员 (0)
- 多线程 (2)
- Jenkins (1)
- zk (1)
- JPA (2)
最新评论
-
zhangzh888:
怎么下载 啊 都没有看见文件
sftp处理文件 -
wx_hello:
怎么得到文件的属性呢? 比如文件的新建时间
sftp处理文件 -
HappyVeryGood:
“运行时异常(即非受控异常)自动强制执行整个逻辑工作单元的回滚 ...
事物管理,spring事物详解,spring @transactional -
skeely1234:
感谢分享,太帅了
eclipse下修改项目名导致tomcat内发布名不一致的解决方法
当我们需要序列化一个JAVA对象时需要实现Serializable接口。这个接口仅仅是一个tag接口,并不需要你真正实现一些方法,因为这个接口没有方法。他作用仅仅是告诉默认JAVA序列化工具,这个对象是可以序列化的。
1.serialVersionUID的作用
当我们的类实现了Serializable接口后,会有一个警告,告诉你需要生成一个serialVersionUID属性。这个serialVersionUID是做什么用的呢?其实这是JAVA序列化的版本控制功能。当序列化对象时会把这个属性写入,当反序列化时则会把这个属性取出,然后与JAVA类中的serialVersionUID属性值对比,如果一致,则认为是同一个版本,正常反序列化,如果不一致则认为版本不同,抛出InvalidClassException异常。
很多时候我们忽略这个警告,并不写这个serialVersionUID属性,但仍然可以正常序列化。那是因为如果没有这个属性,JVM将会根据这个类的属性和方法,计算出一个值作为serialVersionUID的值。这种做法会带来潜在的风险。不同的JVM产生serialVersionUID的算法可能会不一致,如果在不同的环境下产生的serialVersionUID不一致,将导致反序列化失败!
当一个类的结构发生变化,需要改变serialVersionUID,以通知序列化机制此类发生了变化,不兼容原来的版本了!其实并不是只要类结构变化,就必须更改serialVersionUID,JAVA的序列化机制提供了部分变化的兼容机制,有如下几种:
• 添加新的属性 反序列时发现没有此属性,则会赋予该属性默认的类型值
• 添加 writeObject/readObject 方法 因为此方法是用于自定义序列化,不影响序列化
• 删除 writeObject/readObject 方法 同上原因
• 改变属性的访问权限(private protected package public)
• 将一个属性从static变为nonstatic 或者 transient 或者 nontransient
如果你的类改动属于以上范围,默认的JAVA序列化机制可以保证兼容性,也就是说你不需要改动serialVersionUID值。
更多情况参见http://java.sun.com/j2se/1.4/pdf/serial-spec.pdf 5.6.2 Compatible Changes
最近在团队内部发现了一些容易被人们忽视的问题,就是对象的序列化问题。
1.Non Serializable Object
你们有谁去考虑过为什么我们的模型都需要去实现Serializable 接口,大家都应该知道Memcached缓存对象时要求类对需实现 Serializable 这个接口,但最近在项目当中我发现了常常报这么一个异常Non Serializable Object ,大致分析了一下原因是有人把非序列化对象扔到Memcached中导致了这到一个异常。难道这不是一个错误吗?
2.Non-transient non-serializable instance field in Serializable class
这是一个坏味道,意思是在序列化的类中有非序列化的对象,并且没有对非序列化对象标注Transient ,这样做的后果是这个类的实列不能被序列化。
3. 不重视序列号
我常在代码中发现是这样写的,也就是序列化的能力从BaseDomain中继承,但没有加入序列号,实际上序列号是非常有用的,大家想想我们的产品都有版本号,为什么模型却没有?在一个异构的系统当中如果各个系统之间传递消息是用序列化,那么版本号是必不可少的,而且每一次模型变更都要做序列号升级,这样其他系统拿到数据发现序列号不一样,那么其他系统就要考虑升级了,实际上序列化的应用场景还有很多。
其实大部分情况下我们不需要深究哪些改动会影响兼容性。如果我们的序列化仅仅是用作缓存的话,我们可以简单处理,只要改动了类结构,即修改serialVersionUID值,抛弃原先的序列化结果,重新生成!
JAVA序列化过程
JAVA默认的序列化类是ObjectOutputStream,反序列化类是ObjectInputStream。
Java代码
1. public static void main(String[] args) throws Exception {
2.
3. Object o=new Object();
4.
5. try {
6. //序列化
7. FileOutputStream ostream = new FileOutputStream("t.txt");
8. ObjectOutputStream p = new ObjectOutputStream(ostream);
9. p.writeObject(o); // 序列化对象,在内部通过调用defaultWriteFields(Object obj, ObjectStreamClass desc)来序列化对象的所有属性。
10. p.flush();
11. ostream.close();
12. //反序列化
13. FileInputStream fis=new FileInputStream("t.txt");
14. ObjectInputStream istream=new ObjectInputStream(fis);
15. Object s=(ObjectSerializable) istream.readObject();//反序列化对象,内部调用defaultReadFields(Object obj, ObjectStreamClass desc)来反序列化所有属性
16. System.out.println(s);
17. istream.close();
18. fis.close();
19. } catch (IOException ioe) {
20. ioe.printStackTrace();
21. }
22. }
JAVA自定义序列化
自定义序列化根据定制程度的不同,有多种定制方案。
1.Externalizable定制
Externalizable接口继承了Serializable,其中有2个方法:
Java代码
1. void writeExternal(ObjectOutput out) throws IOException;
2. void readExternal(ObjectInput in) throws IOException, ClassNotFoundException;
通过实现Externalizable这个接口,我们可以定制需要序列化的属性。
Java代码
1. /*
2. *ObjectOutputStream在调用writeObject()方法时,会判断需要序列化的类是否继承了
3. *Externalizable接口,如果是,则会调用writeExternal(ObjectOutput out)执行我们
4. *自己写的序列化代码
5. */
6. p.writeObject(o);
Java代码
1. /*
2. *同理,ObjectInputStream在调用readObject()方法时,会判断需要反序列化的类是否继承
3. *了Externalizable接口,如果是,则会调用readExternal(ObjectInput in)执行我们自己
4. *写的反序列化代码
5. */
6. Object s=(ObjectSerializable) istream.readObject()
2.重写ObjectOutputStream/ObjectInputStream
实现Externalizable的方式自定义序列化非常方便,只需要在序列化类内部添加2个方法即可,不需要外部的任何要求。
但是如果我们需要更加深度的定制这还是不够的。Externalizable无法定制序列化对象本身的描述,只能定制对象内部属性的描述。
此时我们需要新建一个自己的序列化类来实现。
Java代码
1. /**
2. * 自定义序列化类
3. */
4. public class CustomObjectOutputStream extends ObjectOutputStream {
5.
6. private OutputStream cusOut;
7.
8. public CustomObjectOutputStream(OutputStream out) throws IOException{
9. /*
10. * 通过调用super()可以将父类的enableOverride设置为true
11. * 当调用父类的writeObject(obj)时,因为enableOverride=true,会调用writeObjectOverride(Object obj)方法
12. * 因此我们需要覆写writeObjectOverride(Object obj)如下所示
13. */
14. super();
15. cusOut=out;
16. }
17.
18. @Override
19. protected void writeObjectOverride(Object obj) throws IOException {
20. //自定义序列化方案
21. //cusOut.write(b)...
22. }
23.
24. }
Java代码
1. /**
2. * 自定义反序列化类
3. */
4. public class CustomObjectInputStream extends ObjectInputStream{
5.
6. private InputStream cusIn;
7.
8. public CustomObjectInputStream(InputStream in)throws IOException {
9. /*
10. * 通过调用super()可以将父类的enableOverride设置为true
11. * 当调用父类的readObject()时,因为enableOverride=true,会调用readObjectOverride()方法
12. * 因此我们需要覆写readObjectOverride()如下所示
13. */
14. super();
15. cusIn=in;
16. }
17.
18. @Override
19. protected Object readObjectOverride() throws IOException,
20. ClassNotFoundException {
21. //自定义反序列化方案
22. //cusIn.read() ...
23. return null;
24. }
25.
26. }
以上2段代码继承了ObjectOutputStream和ObjectInputStream,完全自定义了序列化方法。
既然是完全自定义序列化方法,其实完全没有必要去继承ObjectOutputStream和ObjectInputStream。
上面的代码仅仅适用于做序列化的适配器。其他序列化机制比如hessian,protobuf等,需要适配JAVA默认的序列化机制,则可采用以上的方法适配
1.serialVersionUID的作用
当我们的类实现了Serializable接口后,会有一个警告,告诉你需要生成一个serialVersionUID属性。这个serialVersionUID是做什么用的呢?其实这是JAVA序列化的版本控制功能。当序列化对象时会把这个属性写入,当反序列化时则会把这个属性取出,然后与JAVA类中的serialVersionUID属性值对比,如果一致,则认为是同一个版本,正常反序列化,如果不一致则认为版本不同,抛出InvalidClassException异常。
很多时候我们忽略这个警告,并不写这个serialVersionUID属性,但仍然可以正常序列化。那是因为如果没有这个属性,JVM将会根据这个类的属性和方法,计算出一个值作为serialVersionUID的值。这种做法会带来潜在的风险。不同的JVM产生serialVersionUID的算法可能会不一致,如果在不同的环境下产生的serialVersionUID不一致,将导致反序列化失败!
当一个类的结构发生变化,需要改变serialVersionUID,以通知序列化机制此类发生了变化,不兼容原来的版本了!其实并不是只要类结构变化,就必须更改serialVersionUID,JAVA的序列化机制提供了部分变化的兼容机制,有如下几种:
• 添加新的属性 反序列时发现没有此属性,则会赋予该属性默认的类型值
• 添加 writeObject/readObject 方法 因为此方法是用于自定义序列化,不影响序列化
• 删除 writeObject/readObject 方法 同上原因
• 改变属性的访问权限(private protected package public)
• 将一个属性从static变为nonstatic 或者 transient 或者 nontransient
如果你的类改动属于以上范围,默认的JAVA序列化机制可以保证兼容性,也就是说你不需要改动serialVersionUID值。
更多情况参见http://java.sun.com/j2se/1.4/pdf/serial-spec.pdf 5.6.2 Compatible Changes
最近在团队内部发现了一些容易被人们忽视的问题,就是对象的序列化问题。
1.Non Serializable Object
你们有谁去考虑过为什么我们的模型都需要去实现Serializable 接口,大家都应该知道Memcached缓存对象时要求类对需实现 Serializable 这个接口,但最近在项目当中我发现了常常报这么一个异常Non Serializable Object ,大致分析了一下原因是有人把非序列化对象扔到Memcached中导致了这到一个异常。难道这不是一个错误吗?
2.Non-transient non-serializable instance field in Serializable class
这是一个坏味道,意思是在序列化的类中有非序列化的对象,并且没有对非序列化对象标注Transient ,这样做的后果是这个类的实列不能被序列化。
3. 不重视序列号
我常在代码中发现是这样写的,也就是序列化的能力从BaseDomain中继承,但没有加入序列号,实际上序列号是非常有用的,大家想想我们的产品都有版本号,为什么模型却没有?在一个异构的系统当中如果各个系统之间传递消息是用序列化,那么版本号是必不可少的,而且每一次模型变更都要做序列号升级,这样其他系统拿到数据发现序列号不一样,那么其他系统就要考虑升级了,实际上序列化的应用场景还有很多。
其实大部分情况下我们不需要深究哪些改动会影响兼容性。如果我们的序列化仅仅是用作缓存的话,我们可以简单处理,只要改动了类结构,即修改serialVersionUID值,抛弃原先的序列化结果,重新生成!
JAVA序列化过程
JAVA默认的序列化类是ObjectOutputStream,反序列化类是ObjectInputStream。
Java代码
1. public static void main(String[] args) throws Exception {
2.
3. Object o=new Object();
4.
5. try {
6. //序列化
7. FileOutputStream ostream = new FileOutputStream("t.txt");
8. ObjectOutputStream p = new ObjectOutputStream(ostream);
9. p.writeObject(o); // 序列化对象,在内部通过调用defaultWriteFields(Object obj, ObjectStreamClass desc)来序列化对象的所有属性。
10. p.flush();
11. ostream.close();
12. //反序列化
13. FileInputStream fis=new FileInputStream("t.txt");
14. ObjectInputStream istream=new ObjectInputStream(fis);
15. Object s=(ObjectSerializable) istream.readObject();//反序列化对象,内部调用defaultReadFields(Object obj, ObjectStreamClass desc)来反序列化所有属性
16. System.out.println(s);
17. istream.close();
18. fis.close();
19. } catch (IOException ioe) {
20. ioe.printStackTrace();
21. }
22. }
JAVA自定义序列化
自定义序列化根据定制程度的不同,有多种定制方案。
1.Externalizable定制
Externalizable接口继承了Serializable,其中有2个方法:
Java代码
1. void writeExternal(ObjectOutput out) throws IOException;
2. void readExternal(ObjectInput in) throws IOException, ClassNotFoundException;
通过实现Externalizable这个接口,我们可以定制需要序列化的属性。
Java代码
1. /*
2. *ObjectOutputStream在调用writeObject()方法时,会判断需要序列化的类是否继承了
3. *Externalizable接口,如果是,则会调用writeExternal(ObjectOutput out)执行我们
4. *自己写的序列化代码
5. */
6. p.writeObject(o);
Java代码
1. /*
2. *同理,ObjectInputStream在调用readObject()方法时,会判断需要反序列化的类是否继承
3. *了Externalizable接口,如果是,则会调用readExternal(ObjectInput in)执行我们自己
4. *写的反序列化代码
5. */
6. Object s=(ObjectSerializable) istream.readObject()
2.重写ObjectOutputStream/ObjectInputStream
实现Externalizable的方式自定义序列化非常方便,只需要在序列化类内部添加2个方法即可,不需要外部的任何要求。
但是如果我们需要更加深度的定制这还是不够的。Externalizable无法定制序列化对象本身的描述,只能定制对象内部属性的描述。
此时我们需要新建一个自己的序列化类来实现。
Java代码
1. /**
2. * 自定义序列化类
3. */
4. public class CustomObjectOutputStream extends ObjectOutputStream {
5.
6. private OutputStream cusOut;
7.
8. public CustomObjectOutputStream(OutputStream out) throws IOException{
9. /*
10. * 通过调用super()可以将父类的enableOverride设置为true
11. * 当调用父类的writeObject(obj)时,因为enableOverride=true,会调用writeObjectOverride(Object obj)方法
12. * 因此我们需要覆写writeObjectOverride(Object obj)如下所示
13. */
14. super();
15. cusOut=out;
16. }
17.
18. @Override
19. protected void writeObjectOverride(Object obj) throws IOException {
20. //自定义序列化方案
21. //cusOut.write(b)...
22. }
23.
24. }
Java代码
1. /**
2. * 自定义反序列化类
3. */
4. public class CustomObjectInputStream extends ObjectInputStream{
5.
6. private InputStream cusIn;
7.
8. public CustomObjectInputStream(InputStream in)throws IOException {
9. /*
10. * 通过调用super()可以将父类的enableOverride设置为true
11. * 当调用父类的readObject()时,因为enableOverride=true,会调用readObjectOverride()方法
12. * 因此我们需要覆写readObjectOverride()如下所示
13. */
14. super();
15. cusIn=in;
16. }
17.
18. @Override
19. protected Object readObjectOverride() throws IOException,
20. ClassNotFoundException {
21. //自定义反序列化方案
22. //cusIn.read() ...
23. return null;
24. }
25.
26. }
以上2段代码继承了ObjectOutputStream和ObjectInputStream,完全自定义了序列化方法。
既然是完全自定义序列化方法,其实完全没有必要去继承ObjectOutputStream和ObjectInputStream。
上面的代码仅仅适用于做序列化的适配器。其他序列化机制比如hessian,protobuf等,需要适配JAVA默认的序列化机制,则可采用以上的方法适配
发表评论
-
习惯的开发错误
2014-09-09 17:25 408在一个包的下面 创建一个test.java 文件 这样一个小 ... -
得到指定年份的所有周末
2014-08-20 18:18 1165/** * 得到指定年份的所有周末 */ publi ... -
对对字符串可能出现报空指针的小问题
2014-04-14 14:42 844今天很是郁闷啊,遇到一个基础的问题比对字符串的两种写法: ... -
Java 单例模式详解(转)
2014-03-26 16:52 783概念: java中单例 ... -
往文件里写入字符串
2014-01-20 13:52 1094package ab; import java.io.Bu ... -
Java数组,去掉重复值、增加、删除数组元素
2014-01-02 14:18 5139import java.util.List; import ... -
java定时器的使用(Timer)
2013-10-14 16:42 2406java定时器的使用(Timer) 2008-02-14 13 ... -
JSch - Java实现的SFTP(文件上传详解篇)(转)
2013-10-14 16:40 3401JSch是Java Secure Channel的缩写。JSc ... -
jvm
2013-09-30 15:03 739网上看到一位javaeye的同志写的文章,感觉总结的比较好,虽 ... -
sftp处理文件
2013-09-30 15:02 8025最近工作涉及sftp处理文件,写了个工具类,代码已经测试。请需 ... -
java BigDecimal的使用和四舍五入及格式规范(精准数据)
2013-06-17 15:37 21542• Java中的简单浮点数类型float和double不能够进 ... -
servlet拦截器代码
2013-03-29 13:45 22011- 实现Servlet.Filter接口 public cl ... -
session 超时的时间设置
2013-03-22 14:47 930为单个Web应用 配置超时时间可以在web.xml中使用< ... -
Calendar 获取日期
2013-01-23 10:44 1278Calendar 获取日期 如果想得到某个星期几是什么日期, ... -
JAVA帮助文档全系列
2013-01-05 11:02 0JAVA帮助文档全系列 JDK1.5 JDK1.6 JD ... -
Cannot create a server using the selected type
2012-08-27 11:02 0eclipse中安装tomcat服务器,报错" Ca ... -
线程池(jdk实现)
2012-07-10 15:01 0Sun在Java5中,对Java线程的类库做了大量的扩展,其中 ... -
遍历集合
2012-06-26 17:28 1033* * To change this template, c ... -
权限控制的发散性思维
2012-06-15 17:31 956权限控制的讨论 http://www.iteye.com ... -
(转载)Java设计模式的三大块讲解
2012-06-15 17:27 1161转载自http://www ...
相关推荐
学习Java序列化,里面包含一份PPT以及相应的源码演示
java反序列化工具,覆盖jboss、weblogic、websphere。
java序列化和反序列化java序列化和反序列化java序列化和反序列化
大家请看Java的序列化结构有不足的地方请指教也希望指出不足的地方。
Xson是一个Java对象序列化和反序列化程序。支持Java对象到字节数组的序列化,和从字节数组到Java对象的反序列化。 Maven: <groupId>com.github.xsonorg</groupId> <artifactId>xson-core <version>1.0.1 ...
java 序列化详细解释 很详细 适用于高级软件开发者
java 对象的序列化与反序列化 java 对象的序列化与反序列化
java序列化(Serializable)的作用和反序列化.doc 有详细的讲解哦。 在什么地方用的到都有说明的.
序列化是干什么的? 简单说就是为了保存在内存中的各种对象的状态(也就是实例...虽然你可以用你自己的各种各样的方法来保 存object states,但是Java给你提供一种应该比你自己好的保存对象状态的机制,那就是序列化。
在应用java进行c-s开发的时候,尤其涉及到图片和视频之间的传输时,需要用序列化和反序列化技术,希望对您有帮助
java序列化代码示例,详细讲解序列化作用于使用注意规则项!!!
将java数据 序列化成PHP的格式 a:4:{s:6:"title2";s:13:"这是标题2";s:6:"title3";s:13:"这是标题3";s:5:"title";s:13:"这是标题1";s:6:"title4";s:13:"这是标题4";} 或者a:1:{i:0;a:1:{s:4:"name";s:10:"这是1321";...
Java序列化与反序列化 Java序列化与反序列化 Java序列化与反序列化 Java序列化与反序列化 Java序列化与反序列化
java 常用序列化和反序列化框架使用demo ,java 常用序列化和反序列化框架使用demo
java对象 java序列化 java反序列化
java 序列化,java 序列化,java 序列化,java 序列化,java 序列化,java 序列化
这是Java序列化标准规范,对于研究序列化源码能够提供指导作用,为深入研究Java序列技术奠定基础。
java 的序列化与反序列化举例测试
极好的序列化与发序列化代码。可以处理array集合,数组或者单个对象等的序列化与反序列化。
android(包括java)序列化一个对象传给php去做处理,或是接到php的序列化的对象在java中做处理的工具jar包以及使用方法. 使用方法: byte[] b = null; b = PHPSerializer.serialize(一个对象);//将一个对象序列化后返回...