Java IO之序列化
2015-07-08 22:07
459 查看
序列化机制是Java语言内建的一种对象持久化方式,可以很容易的在JVM中的活动对象和字节数组之间转换。它的一个重要用途就是远程方法调用的时候,用来对开发人员屏蔽底层实现细节(远端的开发人员不知道这个对象的具体实现细节,通过序列化技术可以直接还原为一个对象,直接拿来用即可)。
实际的序列化由ObjectOutputStream和ObjectInputStream来完成。前者可以调用其writeObject方法来将一个Java对象写入流中,后者可以用readObject方法来从流中读取一个Java对象。
在默认的序列化实现中,Java对象的非静态和非瞬时域都会被包括进来,而与域的可见性声明没有关系。
如果你的对象中含有敏感信息,比如user这个对象里面含有password这个域,则如果不想被序列化,必须在前面添加transient关键词。或者添加一个serialPersistentFields域来声明序列化时要包含的域。
在通过ObjectOutputStream的writeObject方法写入对象的时候,如果这个对象定义了writeObject方法,就会调用该方法,并把当前的ObjectOutputStream对象作为参数传递进去。
writeObject方法中一般会包含自定义的序列化逻辑,比如在写入之前修改域的值,或是写入额外的数据等。
在添加自己的逻辑之前,推荐的做法是先调用Java的默认实现,在writeObject方法中通过ObjectOutputStream的defaultWriteObject来完成。在readObject方法实现方式也类似。
所以,必须采取别的方法实现只在远端还原order对象即可。
这个方法就是:用一个替换对象类orderReplace只保存order的ID,在Oder类的writeReplace方法中返回一个OrderReplace对象。这个对象会被作为替代写入到流中,同样,需要OrderReplace类中定义一个readResolve方法,用在读取的时候再转换回Order类对象。
OrderReplace类:
Order类:
如何实现序列化
待序列化的类只要实现Serializable接口即可,该接口是一个标记接口,没有任何方法。实际的序列化由ObjectOutputStream和ObjectInputStream来完成。前者可以调用其writeObject方法来将一个Java对象写入流中,后者可以用readObject方法来从流中读取一个Java对象。
在默认的序列化实现中,Java对象的非静态和非瞬时域都会被包括进来,而与域的可见性声明没有关系。
如果你的对象中含有敏感信息,比如user这个对象里面含有password这个域,则如果不想被序列化,必须在前面添加transient关键词。或者添加一个serialPersistentFields域来声明序列化时要包含的域。
private static final objectStreamField[] serialPersistentFileds = { new ObjectStreamFiled("firstName", String.class); };
自定义对象序列化
通过自定义可以对序列化的过程进行更加细粒度的控制,但是要在类中添加writeObject和readObject方法。在通过ObjectOutputStream的writeObject方法写入对象的时候,如果这个对象定义了writeObject方法,就会调用该方法,并把当前的ObjectOutputStream对象作为参数传递进去。
writeObject方法中一般会包含自定义的序列化逻辑,比如在写入之前修改域的值,或是写入额外的数据等。
在添加自己的逻辑之前,推荐的做法是先调用Java的默认实现,在writeObject方法中通过ObjectOutputStream的defaultWriteObject来完成。在readObject方法实现方式也类似。
private void writeObject(ObjectOutputStream output) throws IOException { output.defaultWriteObject(); // 在这里添加自定义逻辑 output.writeUTF("Hello World"); }
序列化的对象替换
假设你要在网上买东西,在购物表单上添加信息,然后将这个请求发送到远端,即把一个order对象发送到远端,准备在远端将其还原,如果order对象的属性里面有customer的对象引用,则在序列化order的时候,可能也会将customer也序列化。这时候,就涉及到用户的隐私泄露的问题。所以,必须采取别的方法实现只在远端还原order对象即可。
这个方法就是:用一个替换对象类orderReplace只保存order的ID,在Oder类的writeReplace方法中返回一个OrderReplace对象。这个对象会被作为替代写入到流中,同样,需要OrderReplace类中定义一个readResolve方法,用在读取的时候再转换回Order类对象。
OrderReplace类:
private static class OrderReplace implements Serializable { private static final long serialVersionUID = 4654546423735192613L; private String orderId; public OrderReplace(Order order) { this.orderId = order.getId(); } private Object readResolve() throws ObjectStreamException { //根据orderId查找Order对象并返回 } }
Order类:
private Object writeReplace() throws ObjectStreamException { return new OrderReplace(this); }
相关文章推荐
- Java并发——Fork/Join框架
- Java抽象类与接口的区别
- Java连接MySQL数据库
- 《Java从入门到精通》第十二章学习笔记
- eclipse 错误failed to load the jni shared library C:program files/java/ server/jvm.dll
- java文件复制
- SpringMVC+Spring+Mybatis 环境搭建问题记录(注解开发)
- java字符编码
- java.lang.NoClassDefFoundError: Ljavax/transaction/TransactionManager
- Java中的泛型
- Java读取文件夹大小的6种方法及代码
- Java的Set快捷初始化的问题
- Struts2登陆的Demo
- java中jdk安装配置信息
- 关于Struts2中的execute方法
- [LeetCode][Java] Regular Expression Matching
- 【Java】以给定值x为基准将链表分割成两部分,所有小于x的结点排在大于等于x的结点之前
- 用mysql编译:Java Web开发实战经典(基础篇)课后题答案 060502_〖第05章:JSP基础语法〗_第02题
- java导出excel例子
- Java实现Excel导入数据库,数据库中的数据导入到Excel