转自:http://coolxing.iteye.com/blog/1222783#bc2350923
博客分类:
[coolxing按: 转载请注明作者和出处, 如有谬误, 欢迎在评论中指正.]
java的序列化机制支持将对象序列化为本地文件或者通过网络传输至别处, 而反序列化则可以读取流中的数据, 并将其转换为java对象. 被序列化的类需要实现Serializable接口, 使用ObjectInputStream和ObjectOutputStream进行对象的读写操作.
当然, java的序列化机制并非如此简单, 以下是个人总结的一些知识点:
1. 对象读取的顺序应该和写入的顺序一致, 而且读取的次数不能超过已写入对象的个数. 比如文件中仅仅存在2个对象, 就不能连续调用3次readObject()方法, 除非调用了reset, skip等对流重新定位的方法.
2. java序列化机制针对的是对象, 而不是类. 因此只有非静态成员变量才会被序列化成二进制数据.
3. 使用transient关键字修饰的成员变量不会被序列化为二进制数据.
4. 将对象序列化为二进制数据, 将二进制数据反序列化为java对象, 这两个操作可能位于不同的应用中, 甚至也可能在不同的计算机上进行. 需要保证这两种场合下都有class文件, 在序列化处和反序列处的class文件需要完成一致, 包括包名.
5. 序列化ID的作用. 上面的Person类中定义了序列化ID: private static final long serialVersionUID = 1L;
这是一个非强制定义的静态成员, 如果不定义序列化ID, 那么eclipse会给出一个黄色的警告, 这个警告可以忽略.
考虑这样的情形: Person类定义了序列化ID, 且序列化对象时serialVersionUID的值为1, 而反序列化时serialVersionUID的值不为1, 那么此时将无法反序列化成功. 所以序列化ID可以用来限制某些用户的反序列化.
6. 父类的序列化问题. 根据java的对象实例化机制可知, 创建一个子类对象的过程中, 会创建其父类对象, 反序列化也不例外. 如果一个类实现了Serializable接口, 而其父类却没有实现Serializable接口, 那么在反序列化时, 虚拟机会调用父类的无参构造函数创建父类对象, 因此反序列化后父类成员变量的值为调用无参构造函数之后的值. 如果父类既没有实现Serializable接口, 也不存在无参构造函数, 那么在反序列化时将发生程序错误.
假设存在一个没有实现Serializable接口的Male类:
- publicclass Male {
- private String name;
- privateint age;
- public Male() {
- }
- public String getName() {
- return name;
- }
- publicvoid setName(String name) {
- this.name = name;
- }
- publicint getAge() {
- return age;
- }
- publicvoid setAge(int age) {
- this.age = age;
- }
- @Override
- public String toString() {
- return"Male [name=" + name + ", age=" + age + "]";
- }
- }
public class Male { private String name; private int age; public Male() { } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override public String toString() { return "Male [name=" + name + ", age=" + age + "]"; } }
Male的子类MaleStudent则实现了Serializable接口:
- publicclass MaleStudent extends Male implements Serializable {
- privateint studentID;
- public MaleStudent(int studentID) {
- super();
- this.studentID = studentID;
- }
- publicint getStudentID() {
- return studentID;
- }
- publicvoid setStudentID(int studentID) {
- this.studentID = studentID;
- }
- @Override
- public String toString() {
- return"MaleStudent [studentID=" + studentID + "]";
- }
- }
public class MaleStudent extends Male implements Serializable { private int studentID; public MaleStudent(int studentID) { super(); this.studentID = studentID; } public int getStudentID() { return studentID; } public void setStudentID(int studentID) { this.studentID = studentID; } @Override public String toString() { return "MaleStudent [studentID=" + studentID + "]"; } }
则反序列化MaleStudent对象后, 其name和age属性都发生了改变:
- MaleStudent student = new MaleStudent(1);
- student.setName("coolxing");
- student.setAge(24);
- ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(
- "male.obj"));
- out.writeObject(student);
- out.close();
- ObjectInputStream in = new ObjectInputStream(new FileInputStream(
- "male.obj"));
- MaleStudent maleStudent = (MaleStudent) in.readObject();
- System.out.println(maleStudent.getName() + ", " + maleStudent.getAge()
- + ", " + maleStudent.getStudentID());
MaleStudent student = new MaleStudent(1); student.setName("coolxing"); student.setAge(24); ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream( "male.obj")); out.writeObject(student); out.close(); ObjectInputStream in = new ObjectInputStream(new FileInputStream( "male.obj")); MaleStudent maleStudent = (MaleStudent) in.readObject(); System.out.println(maleStudent.getName() + ", " + maleStudent.getAge() + ", " + maleStudent.getStudentID());
程序的输出为:
name = null, age = 0, studentID = 1
- publicclass User implements Serializable {
- privatestaticfinallong serialVersionUID = 1L;
- private String userName;
- private String passWord;
- public User(String userName, String passWord) {
- this.userName = userName;
- this.passWord = passWord;
- }
- public User() {
- }
- privatevoid writeObject(ObjectOutputStream out) {
- try {
- PutField field = out.putFields();
- field.put("userName", userName);
- System.out.println("加密前: passWord = " + passWord);
- // 模拟加密
- passWord = passWord + "1";
- System.out.println("加密后: passWord = " + passWord);
- field.put("passWord", passWord);
- out.writeFields();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- privatevoid readObject(ObjectInputStream in) {
- try {
- GetField field = in.readFields();
- userName = (String) field.get("userName", "");
- passWord = (String) field.get("passWord", "");
- System.out.println("读取的原始passWord = " + passWord);
- // 模拟解密
- passWord = passWord.substring(0, passWord.length() - 1);
- System.out.println("解密后的passWord = " + passWord);
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- }
public class User implements Serializable { private static final long serialVersionUID = 1L; private String userName; private String passWord; public User(String userName, String passWord) { this.userName = userName; this.passWord = passWord; } public User() { } private void writeObject(ObjectOutputStream out) { try { PutField field = out.putFields(); field.put("userName", userName); System.out.println("加密前: passWord = " + passWord); // 模拟加密 passWord = passWord + "1"; System.out.println("加密后: passWord = " + passWord); field.put("passWord", passWord); out.writeFields(); } catch (IOException e) { e.printStackTrace(); } } private void readObject(ObjectInputStream in) { try { GetField field = in.readFields(); userName = (String) field.get("userName", ""); passWord = (String) field.get("passWord", ""); System.out.println("读取的原始passWord = " + passWord); // 模拟解密 passWord = passWord.substring(0, passWord.length() - 1); System.out.println("解密后的passWord = " + passWord); } catch (Exception e) { e.printStackTrace(); } } }
- File file = new File("user.obj");
- User user = new User("coolxing", "1987810");
- ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("user.obj"));
- out.writeObject(user);
- System.out.println(file.length());
- // 改变userName的值后再次将user对象存入文件
- user.setUserName("min");
- out.writeObject(user);
- System.out.println(file.length());
- ObjectInputStream in = new ObjectInputStream(new FileInputStream("user.obj"));
- User userFromFile1 = (User) in.readObject();
- User userFromFile2 = (User) in.readObject();
- System.out.println(userFromFile1.toString());
- System.out.println(userFromFile2.toString());
File file = new File("user.obj"); User user = new User("coolxing", "1987810"); ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("user.obj")); out.writeObject(user); System.out.println(file.length()); // 改变userName的值后再次将user对象存入文件 user.setUserName("min"); out.writeObject(user); System.out.println(file.length()); ObjectInputStream in = new ObjectInputStream(new FileInputStream("user.obj")); User userFromFile1 = (User) in.readObject(); User userFromFile2 = (User) in.readObject(); System.out.println(userFromFile1.toString()); System.out.println(userFromFile2.toString());
程序的输出结果为:
109
114
User [userName=coolxing, passWord=1987810]
User [userName=coolxing, passWord=1987810]
程序中调用了2次readObject()方法, 且没有出现程序错误, 由此可知确实向文件中写入了2个对象. 第二次写入user对象时, 系统发现文件中已经存在user对象, 将不再存入user对象的内容, 只写入一个引用和一些控制信息, 所以第二次写入user对象后文件的大小增加的很少, 而且userName也没有发生改变.
9. 如果一个类中包含非基本数据类型的成员变量, 那么不仅类本身需要实现Serializable接口, 类中的非基本数据类型也需要实现Serializable接口. java的一些核心类, 如String,
基本数据类型的包装类等都已经实现了Serializable接口, 使用的时候可以查看文档.
10. 对于包含集合型成员的类来说, 不仅类本身需要现Serializable接口, 集合中所存储的元素也要实现Serializable接口.
那么集合类(List, Set, Map)到底有没有实现Serializable接口呢? 这是我疑惑的地方, 文档中并没有说明. 可以确定的是,
只要集合中的元素是可序列化的, 序列化过程就不会出错.
关于java序列化机制的一些其他方面的叙述, 请参见http://www.ibm.com/developerworks/cn/java/j-5things1/index.html?ca=drs-cn-0504
相关推荐
5.2.4 对象实现机制 为了方便开发人员将Java对象进行序列化及反序列化,Java提供了一套方便的API来支持。其中包括以下接口和类: java.io.Serializable java.io.Externalizable ObjectOutput ObjectInput ...
学习Java序列化,里面包含一份PPT以及相应的源码演示
java反序列化工具,覆盖jboss、weblogic、websphere。
java序列化和反序列化java序列化和反序列化java序列化和反序列化
java 对象的序列化与反序列化 java 对象的序列化与反序列化
Xson是一个Java对象序列化和反序列化程序。支持Java对象到字节数组的序列化,和从字节数组到Java对象的反序列化。 Maven: <groupId>com.github.xsonorg</groupId> <artifactId>xson-core <version>1.0.1 ...
大家请看Java的序列化结构有不足的地方请指教也希望指出不足的地方。
java 序列化详细解释 很详细 适用于高级软件开发者
序列化是干什么的? 简单说就是为了保存在内存中的各种对象的状态(也就是实例...虽然你可以用你自己的各种各样的方法来保 存object states,但是Java给你提供一种应该比你自己好的保存对象状态的机制,那就是序列化。
Java序列化API提供一种处理对象序列化的标准机制。在这里你能学到如何序列化一个对象,什么时候需要序列化以及Java序列化的算法,我们用一个实例来示范序列化以后的字节是如何描述一个对象的信息的。……
在应用java进行c-s开发的时候,尤其涉及到图片和视频之间的传输时,需要用序列化和反序列化技术,希望对您有帮助
java序列化(Serializable)的作用和反序列化.doc 有详细的讲解哦。 在什么地方用的到都有说明的.
java序列化代码示例,详细讲解序列化作用于使用注意规则项!!!
Java序列化机制(2)- serialVersionUID 实验 http://blog.csdn.net/suileisl/article/details/16991753
什么是java序列化,如何实现java序列化?学习.pdf
Java序列化与反序列化 Java序列化与反序列化 Java序列化与反序列化 Java序列化与反序列化 Java序列化与反序列化
java 常用序列化和反序列化框架使用demo ,java 常用序列化和反序列化框架使用demo
java对象 java序列化 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";...