java中clone方法_java中的clone 方法

java的序列化和反序列化;

定义:序列化是指把一个对象写到一个输出流中;对象的反序列化是指从一个输入流中读取一个对象.只要实现了java.io.Serializable(标识接口)接口的对象才能被序列化和反序列化;

序列化的步骤:

1).创建一个对象输出流,它可以包装一个其他类型的输出流,比如文件输出流.

ObjectOutputStream out=new ObjectOutputStream(new fileOutputStream("c:/a.obj"));

2).通过对象输出流的writeObject()方法写对象

out.writeObject("hello");

out.close;

以上代码将一个String 对象保存到文件中.

对象的反序列化步骤:

1).创建一个对象输入流,他可以包装一个其他类型的输入流,例如文件输入流.

ObjectInputStream in=new ObjectInputStream(new FileInputStream("c:/a.obj"));

2).通过对象输入流的readObject()方法读取对象.

String obj=(String)in.readObject();

in.close();

当写入多个对象时,为了能正确读出数据,必须保证向输出流写对象的顺序与从输入流读对象的顺序相同.

一个简单的序列化 反序列化的例子:

=======================================================================================

Customer类(实现了Serializable标识接口)

import java.io.Serializable;

import java.util.Date;

public class Customer implements Serializable {

private String name;

private Date birthday;

private transientString password; 注释① public String getPassword() {

return password;

}

public void setPassword(String password) {

this.password = password;

}

public Customer(String name,String password)

{

this.name=name;

this.birthday=new Date();

this.password=password;

}

public Date getBirthday() {

return birthday;

}

public void setBirthday(Date birthday) {

this.birthday = birthday;

}

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

}

ObjectSaver类:执行序列化,将类写到文件中

import java.io.FileInputStream;

import java.io.FileNotFoundException;

import java.io.FileOutputStream;

import java.io.IOException;

import java.io.ObjectInputStream;

import java.io.ObjectOutputStream;

import java.util.Date;

public class ObjectSaver

{

public ObjectSaver()

{

try {

ObjectOutputStream out=new ObjectOutputStream(new FileOutputStream("c:/a.obj"));

String obj1="序列化对象";

Date obj2=new Date();

Customer obj3=new Customer("jalion","123456");

//序列化对象

out.writeObject(obj1);

out.writeObject(obj2);

out.writeObject(obj3);

out.close();

System.out.println("需要序列化的对象:"+obj1);

System.out.println("需要序列化的对象:"+obj2);

System.out.println("需要序列化的对象:"+obj3.getName()+"生日"+obj3.getBirthday()+"密码:"+obj3.getPassword());

} catch (FileNotFoundException e) {

e.printStackTrace();

} catch (IOException e) {

e.printStackTrace();

}

}

public static void main(String args[])

{

new ObjectSaver();

}

}

ObjectRead:反序列化类 从文件中读取对象

import java.io.FileInputStream;

import java.io.FileNotFoundException;

import java.io.IOException;

import java.io.ObjectInputStream;

import java.util.Date;

public class ObjectRead {

public static void main(String args[])

{

//  反序列化对象

ObjectInputStream in;

try {

in = new ObjectInputStream(new FileInputStream("c:/a.obj"));

String obj11=(String)in.readObject();

Date obj22=(Date)in.readObject();

Customer obj33=(Customer)in.readObject();

System.out.println("反序列化的对象:"+obj11);

System.out.println("反序列化的对象:"+obj22);

System.out.println("反序列化的对象:"+obj33.getName()+"生日"+obj33.getBirthday()+"密码:"+obj33.getPassword());

in.close();

} catch (FileNotFoundException e) {

e.printStackTrace();

} catch (IOException e) {

e.printStackTrace();

} catch (ClassNotFoundException e) {

e.printStackTrace();

}

}

}

说明:由于String和Date类都实现了Serializable接口,所以可以序列化,要进行序列化的类包括其属性中引用的类必须全部实现Serializable接口才能序列化,否则将会抛出java.io.NotSerializableException异常.

========================================================================================

注释①在类Customer中,有个属性password,由于将类序列化保存在文件中,可以通过网络传输,当password比较重要时,很容易通过读取文件或者拦截网络数据来得到password,所以应当禁止对这种属性序列化.解决办法就是将这个属性用transient修饰,例如例子中的注释处.当属性有transient修饰时,不进行序列化.

ObjectRead运行结果如下:

当有transient修饰时:

反序列化的对象:序列化对象

反序列化的对象:Tue May 08 10:56:40 CST 2007

反序列化的对象:jalion生日Tue May 08 10:56:40 CST 2007密码:null

当没有transient修饰时:

反序列化的对象:序列化对象

反序列化的对象:Tue May 08 10:56:40 CST 2007

反序列化的对象:jalion生日Tue May 08 10:56:40 CST 2007密码:123456

&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&

除了用以上方案,来保证传输过程中的安全,还可以用通过进一步控制序列化和反序列化的方式,来达到将password加密或其他方式来实现序列化.

可以在Costumer类中提供一个readObject()和writeObject()方法,当ObjectOutputStream对一个对象序列化时,如果该对象具有writeObject()方法,那么就会执行这一方法,否则就按默认的方式序列化,在writeObject()方法中,可以调用defaultWriteObject()方法,使得对象输出流执行默认的序列化操作.反序列化同理.在修改后的Costumer类中,提供了readObject()和writeObject()方法,使得transient类型的password属性能够进行特殊的序列化

①private void writeObject(ObjectOutputStream stream){}

②private void readObject (ObjectInputStream stream) {}

以上两个方法并不是在Serializable接口中实现的.如果要进一步控制序列化的方式,就可以实现这两个方法,方法名必须与方法①②完全一致.

=========================================================================

修改后的Customer类

import java.io.IOException;

import java.io.ObjectInputStream;

import java.io.ObjectOutputStream;

import java.io.Serializable;

import java.util.Date;

public class Customer implements Serializable {

private String name;

private Date birthday;

private transient String password;

public String getPassword() {

return password;

}

public void setPassword(String password) {

this.password = password;

}

public Customer(String name,String password)

{

this.name=name;

this.birthday=new Date();

this.password=password;

}

public Date getBirthday() {

return birthday;

}

public void setBirthday(Date birthday) {

this.birthday = birthday;

}

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

private void writeObject(ObjectOutputStream stream)

{

try {

stream.defaultWriteObject();//先按默认的方式序列化

stream.writeObject(jiami(password));

} catch (Exception e) {

// TODO 自动生成 catch 块

e.printStackTrace();

}

}

private void readObject(ObjectInputStream stream)

{

try {

stream.defaultReadObject();//先按默认的方式反序列化

password=jiemi((String)stream.readObject());

} catch (Exception e) {

// TODO 自动生成 catch 块

e.printStackTrace();

}

}

private String jiami(String password) //加密解密示意

{

return "gthgthg"+password;

}

private String jiemi(String password) //解密示意

{

String s=password.substring(7,password.length());

return s;

}

}

posted on 2007-07-01 10:08 李桢 阅读(545) 评论(0)  编辑  收藏 所属分类: java

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值