Java序列化Serializable解析
来源:互联网 发布:壹卡会可以在淘宝用吗 编辑:程序博客网 时间:2024/05/17 08:29
引入
我们知道在java中一切即对象,那我们如果想存储对象或者传送对象时该怎么办?对象又不是字节或者字符,不能直接用输入输出流来进行读写。这时就用到序列化了。
概念
维基百科上的定义是:
对同步控制而言,表示强制在同一时间内进行单一存取。
在数据储存与传送的部分是指将一个对象存储至一个储存媒介,例如档案或是记亿体缓冲等,或者透过网络传送资料时进行编码的过程,可以是字节或是XML等格式。而字节的或XML编码格式可以还原完全相等的对象。这程序被应用在不同应用程序之间传送对象,以及服务器将对象储存到档案或数据库。相反的过程又称为反序列化。
这篇博客主要讲数据储存与传送的定义。我们知道在java中一切即对象,那我们如果想存储对象或者传送对象时该怎么办?对象又不是字节或者字符,不能直接用输入输出流来进行读写。
那么这时我们对对象的操作就应该把对象转换为字节序列,而后采用输入输出流来进行操作。比如存储到硬盘或者在网络中传输,以达到传递对象的目的。
当你从硬盘中取出或者在网络中接收到字节序列后,再转换为对象,即反序列化。
实现
只有实现了Serializable和Externalizable接口的类的对象才能被序列化。
ObjectOutputStream类中的writeObject()方法用来写序列化的对象。ObjectInputStream的readObject()方法读取对象。
import java.io.*;public class Main { public static void main(String[] args)throws Exception { Person person = new Person(); person.setName("小明"); person.setAge(19); person.setSex("男"); ObjectOutputStream oo = new ObjectOutputStream(new FileOutputStream(new File("/Users/lixingyu/object.txt"))); oo.writeObject(person); oo.close(); System.out.print("write ok !\n"); ObjectInputStream oi = new ObjectInputStream(new FileInputStream(new File("/Users/lixingyu/object.txt"))); Person person1 = (Person) oi.readObject(); System.out.print(person1.getName()+"\n"); System.out.print("read ok!\n"); } static class Person implements Serializable{ private static final long serialVersionUID = -5809782578272943999L; public String name; public int age; public String sex; 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; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } }}
serialVersionUID
注意到上面的代码中有个serialVersionUID,而且只有一个初始化,下面的代码并没有用到该变量,那么它是干什么的呢?
如果我们对上面的内部类做个修改,删除该变量,先将对象存入硬盘,再在Person类中增加一个变量friend,读取会有什么结果呢?(这里要运行两次,一次只存,第二次,增加变量后只读。
import java.io.*;public class Main { public static void main(String[] args)throws Exception { Person person = new Person(); person.setName("小明"); person.setAge(19); person.setSex("男");// ObjectOutputStream oo = new ObjectOutputStream(new FileOutputStream(new File("/Users/lixingyu/object.txt")));// oo.writeObject(person);// oo.close(); System.out.print("write ok !\n"); ObjectInputStream oi = new ObjectInputStream(new FileInputStream(new File("/Users/lixingyu/object.txt"))); Person person1 = (Person) oi.readObject(); System.out.print(person1.getName()+"\n"); System.out.print("read ok!\n"); } static class Person implements Serializable{// private static final long serialVersionUID = -5809782578272943999L; public String name; public int age; public String sex; public String friends; 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; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } }}
你会看到下面的报错信息:
Exception in thread "main" java.io.InvalidClassException: Main$Person; local class incompatible: stream classdesc serialVersionUID = -3488593190474644338, local class serialVersionUID = 1566115588131499685 at java.io.ObjectStreamClass.initNonProxy(ObjectStreamClass.java:616) at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1623) at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1518) at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1774) at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1351) at java.io.ObjectInputStream.readObject(ObjectInputStream.java:371) at Main.main(Main.java:15) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:497) at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)
事实上,如果你没有为类添加serializableUID,编译器会自动添加生产一个ID,而当我们对实现序列化的接口类的源代码文件,做修改,即使是只添加一个空格,编译器也会生成一个不同的ID,这样当读取之前存放到硬盘上的序列化对象时,编译器会报错,拒绝载入。
所以serializableUID是用来区别序列化对象的,必须要添加,否则很容易出错。
用途
比如上面的从硬盘中存取对象;在android开发中利用Intent在Activity之间传递对象时,有一种方法是,要求这个对象必须是序列化的;还有通过网络传递对象。
- Java序列化Serializable解析
- Serializable java序列化
- java序列化-Serializable
- Serializable java序列化
- Serializable java序列化
- Serializable java序列化
- JAVA序列化Serializable
- Serializable java序列化
- java序列化Serializable
- Serializable java序列化
- Serializable java序列化
- java Serializable 序列化
- Serializable java序列化
- java 序列化Serializable
- Serializable java序列化
- java序列化Serializable
- java序列化Serializable
- Serializable java序列化
- KMP算法
- mpich2 联机运行方法和问题2.
- 按钮和复选框控件
- MVC和MVP到底有什么区别呢?
- 43243
- Java序列化Serializable解析
- 使用 Environment Indicator 模块区分不同的 Drupal 环境
- AutoLayout
- 【Boost】boost库中thread多线程详解11——线程的休眠和中断
- 指针,数组,引用之间的不同点
- php生成二维码
- intent的startActivityForResult()方法使用注意事情
- js控制横向滚动条居中,鼠标在页面中的坐标
- Spring Context 启动错误