java序列化接口_java序列化接口Serializable的使用

来自:http://wang09si.blog.163.com/blog/static/170171804201373195046397/

首先要明白,什么是序列化?

我们经常看到一个实体类实现Serializable接口,这种用法就是序列化。目的是保存对象的状态,以便将它读取出来。

序列化就是将一个对象的状态(各个属性量)保存起来,然后在适当的时候再获得。

序列化将数据分解成字节流,以便存储在文件中或在网络上传输。反序列化就是打开字节流并重构对象。对象序列化不仅要将基本数据类型转换成字节表示,有时还要恢复数据。恢复数据要求有恢复数据的对象实例

Java为我们提供一种比较好的保存对象状态的机制,那就是序列化。

也就是说,保存状态和读取状态的事java已经帮我们做了,我们只需调相应的方法就可以了。

序列化的什么特点:

如果某个类能够被序列化,其子类也可以被序列化。声明为static和transient类型的成员数据不能被序列化。因为static代表类的状态,

transient代表对象的临时数据。

其次要搞清楚,什么情况下需要实例化?

1、当你想把的内存中的对象状态保存到一个文件中或者数据库中时候;

2、当你想用套接字在网络上传送对象的时候;

java

对象序列化不仅保留一个对象的数据,而且递归保存对象引用的每个对象的数据。可以将整个对象层次写入字节流中,可以保存在文件中或在网络连接上传递。利用

对象序列化可以进行对象的"深复制",即复制对象本身及引用的对象本身。序列化一个对象可能得到整个对象序列。

3、当你想通过RMI传输对象的时候;

RMI要利用对象序列化运行远程主机上的服务,就像在本地机上运行对象时一样。

最后,就是如何实现序列化的?

在没有序列化前,每个保存在堆(Heap)中的对象都有相应的状态(state),即实例变量(instance

ariable)比如:

Foo  myFoo = new Foo();

myFoo .setWidth(37);

myFoo.setHeight(70);

当通过下面的代码序列化之后,MyFoo对象中的width和Height实例变量的值(37,70)都被保存到foo.ser文件中,这样以后又可以把它

从文件中读出来,重新在堆中创建原来的对象。当然保存时候不仅仅是保存对象的实例变量的值,JVM还要保存一些小量信息,比如类的类型等以便恢复原来的对象。

FileOutputStream

fs = new FileOutputStream("foo.ser");

ObjectOutputStream os = new

ObjectOutputStream(fs);

os.writeObject(myBox);

os.close();

ObjectInputStream

in = new ObjectInputStream (new FileInputStream("foo.ser"));

Box box = (Box)

(in.readObject());

System.out.println(box.toString());

System.out.println(box.height);

in.close();

完整例子:

package wzq.j2se.erializables;

import java.io.FileInputStream;

import java.io.FileOutputStream;

import

java.io.ObjectInputStream;

import java.io.ObjectOutputStream;

import

java.io.Serializable;

public class Box implements Serializable {

private int width;

private

int height;

public void setWidth(int width) {

this.width = width;

}

public void setHeight(int height) {

this.height = height;

}

public static void main(String[] args) {

Box myBox = new

Box();

myBox.setWidth(50);

myBox.setHeight(30);

try

{

FileOutputStream fs = new

FileOutputStream("foo.ser");

ObjectOutputStream os = new

ObjectOutputStream(fs);

os.writeObject(myBox);

os.close();

ObjectInputStream

in = new ObjectInputStream (new FileInputStream("foo.ser"));

Box box =

(Box)

(in.readObject());

System.out.println(box.toString());

System.out.println(box.height);

in.close();

}

catch (Exception ex) {

ex.printStackTrace();

}

}

} //

writeObject和readObject本身就是线程安全的,传输过程中是不允许被并发访问的。所以对象能一个一个接连不断的传过来

子类:

package

wzq.j2se.erializables;

import java.io.FileInputStream;

import java.io.FileOutputStream;

import

java.io.ObjectInputStream;

import java.io.ObjectOutputStream;

public class ExtendsBox extends Box{

int age;

public int getAge() {

return age;

}

public void setAge(int age) {

this.age = age;

}

public

static void main(String[] args) {

ExtendsBox eb = new

ExtendsBox();

eb.setAge(101);

try {

FileOutputStream fs = new

FileOutputStream("abc");

ObjectOutputStream os = new

ObjectOutputStream(fs);

os.writeObject(eb);

os.close();

ObjectInputStream

in = new ObjectInputStream (new FileInputStream("abc"));

ExtendsBox box =

(ExtendsBox)

(in.readObject());

System.out.println(box.toString());

System.out.println(box.getAge());

in.close();

}

catch (Exception ex)

{

ex.printStackTrace();

}

}

}

首先要明白,什么是序列化?

我们经常看到一个实体类实现Serializable接口,这种用法就是序列化。目的是保存对象的状态,以便将它读取出来。

序列化就是将一个对象的状态(各个属性量)保存起来,然后在适当的时候再获得。

序列化将数据分解成字节流,以便存储在文件中或在网络上传输。反序列化就是打开字节流并重构对象。对象序列化不仅要将基本数据类型转换成字节表示,有时还要恢复数据。恢复数据要求有恢复数据的对象实例

Java为我们提供一种比较好的保存对象状态的机制,那就是序列化。

也就是说,保存状态和读取状态的事java已经帮我们做了,我们只需调相应的方法就可以了。

序列化的什么特点:

如果某个类能够被序列化,其子类也可以被序列化。声明为static和transient类型的成员数据不能被序列化。因为static代表类的状态,

transient代表对象的临时数据。

其次要搞清楚,什么情况下需要实例化?

1、当你想把的内存中的对象状态保存到一个文件中或者数据库中时候;

2、当你想用套接字在网络上传送对象的时候;

java

对象序列化不仅保留一个对象的数据,而且递归保存对象引用的每个对象的数据。可以将整个对象层次写入字节流中,可以保存在文件中或在网络连接上传递。利用

对象序列化可以进行对象的"深复制",即复制对象本身及引用的对象本身。序列化一个对象可能得到整个对象序列。

3、当你想通过RMI传输对象的时候;

RMI要利用对象序列化运行远程主机上的服务,就像在本地机上运行对象时一样。

最后,就是如何实现序列化的?

在没有序列化前,每个保存在堆(Heap)中的对象都有相应的状态(state),即实例变量(instance

ariable)比如:

Foo  myFoo = new Foo();

myFoo .setWidth(37);

myFoo.setHeight(70);

当通过下面的代码序列化之后,MyFoo对象中的width和Height实例变量的值(37,70)都被保存到foo.ser文件中,这样以后又可以把它

从文件中读出来,重新在堆中创建原来的对象。当然保存时候不仅仅是保存对象的实例变量的值,JVM还要保存一些小量信息,比如类的类型等以便恢复原来的对象。

FileOutputStream

fs = new FileOutputStream("foo.ser");

ObjectOutputStream os = new

ObjectOutputStream(fs);

os.writeObject(myBox);

os.close();

ObjectInputStream

in = new ObjectInputStream (new FileInputStream("foo.ser"));

Box box = (Box)

(in.readObject());

System.out.println(box.toString());

System.out.println(box.height);

in.close();

完整例子:

package wzq.j2se.erializables;

import java.io.FileInputStream;

import java.io.FileOutputStream;

import

java.io.ObjectInputStream;

import java.io.ObjectOutputStream;

import

java.io.Serializable;

public class Box implements Serializable {

private int width;

private

int height;

public void setWidth(int width) {

this.width = width;

}

public void setHeight(int height) {

this.height = height;

}

public static void main(String[] args) {

Box myBox = new

Box();

myBox.setWidth(50);

myBox.setHeight(30);

try

{

FileOutputStream fs = new

FileOutputStream("foo.ser");

ObjectOutputStream os = new

ObjectOutputStream(fs);

os.writeObject(myBox);

os.close();

ObjectInputStream

in = new ObjectInputStream (new FileInputStream("foo.ser"));

Box box =

(Box)

(in.readObject());

System.out.println(box.toString());

System.out.println(box.height);

in.close();

}

catch (Exception ex) {

ex.printStackTrace();

}

}

} //

writeObject和readObject本身就是线程安全的,传输过程中是不允许被并发访问的。所以对象能一个一个接连不断的传过来

子类:

package wzq.j2se.erializables;

import java.io.FileInputStream;

import java.io.FileOutputStream;

import

java.io.ObjectInputStream;

import java.io.ObjectOutputStream;

public class ExtendsBox extends Box{

int age;

public int getAge() {

return age;

}

public void setAge(int age) {

this.age = age;

}

public

static void main(String[] args) {

ExtendsBox eb = new

ExtendsBox();

eb.setAge(101);

try {

FileOutputStream fs = new

FileOutputStream("abc");

ObjectOutputStream os = new

ObjectOutputStream(fs);

os.writeObject(eb);

os.close();

ObjectInputStream

in = new ObjectInputStream (new FileInputStream("abc"));

ExtendsBox box =

(ExtendsBox)

(in.readObject());

System.out.println(box.toString());

System.out.println(box.getAge());

in.close();

}

catch (Exception ex) {

ex.printStackTrace();

}

}

}

serialVersionUID作用:

序列化时为了保持版本的兼容性,即在版本升级时反序列化仍保持对象的唯一性。

有两种生成方式:

一个是默认的1L,比如:private

static final long serialVersionUID = 1L;

一个是根据类名、接口名、成员方法及属性等来生成一个64位的哈希字段,比如:

private static final   long

serialVersionUID = xxxxL;

当你一个类实现了Serializable接口,如果没有定义serialVersionUID,Eclipse会提供这个提示功能告诉你去定义

。在Eclipse中点击类中warning的图标一下,Eclipse就会自动给定两种生成的方式。如果不想定义它,在Eclipse的设置中也

可以把它关掉的,设置如下:

Window ==> Preferences ==> Java ==> Compiler

==> Error/Warnings ==>

Potential programming problems

将Serializable class without serialVersionUID的warning改成ignore即可。

如果你没有考虑到兼容性问题时,就把它关掉,不过有这个功能是好的,只要任何类别实现了Serializable这个接口的话,如果没有加入

serialVersionUID,Eclipse都会给你warning提示,这个serialVersionUID为了让该类别

Serializable向后兼容。

如果你的类Serialized存到硬盘上面后,可是后来你却更改了类别的field(增加或减少或改名),当你Deserialize时,就会出现Exception的,这样就会造成不兼容性的问题。

但当serialVersionUID相同时,它就会将不一样的field以type的预设值Deserialize,可避开不兼容性问题。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值