原地址:http://201211131343.iteye.com/blog/1772780
- 博客分类:
- Java
如果我们想利用网络传输对象或者将对象内部状态持久化,那么该对象必须是可序列化的。
类的可序列化很简单,只需实现serializable或者externalizable接口即可。
通常情况下,如果一个类仅仅实现了serializable接口,序列化框架为我们提供了一个默认的序列化形式。
如果想要自定义序列化形式,就要考虑添加readObject方法和对应的writeObject方法。详细方法签名如下:
- private void readObject() throws ClassNotFoundException,IOException
- private void writeObject() throws IOException
private void readObject() throws ClassNotFoundException,IOException
private void writeObject() throws IOException
以上方法并不是Object的方法,该方法的调用是利用反射机制实现的。另外除了以上两个方法以外,还有另外三个于序列化有关的方法:
- ANY-ACCESS-MODIFIER Object writeReplace() throws ObjectStreamException;
- NY-ACCESS-MODIFIER Object readResolve() throws ObjectStreamException;
- private void readObjectNoData()
- throws ObjectStreamException;
ANY-ACCESS-MODIFIER Object writeReplace() throws ObjectStreamException;
ANY-ACCESS-MODIFIER Object readResolve() throws ObjectStreamException;
private void readObjectNoData()
throws ObjectStreamException;
除了实现serialiable接口以外,还可以实现externalizable接口。该接口继承自serializable接口,并且包含了两个抽象方法:
- void writeExternal(ObjectOutput out) throws IOException;
- void readExternal(ObjectInput in) throws IOException, ClassNotFoundException;
void writeExternal(ObjectOutput out) throws IOException;
void readExternal(ObjectInput in) throws IOException, ClassNotFoundException;
因此,实现externalizable接口的类的序列化必须由该类自身来提供,具体的实现分别写在抽象方法中。
通过调用writeExternal方法实现对象的序列化
通过调用readExternal方法实现对象的反序列化(该方法调用之前会调用可序列化类的默认构造方法,因此该类必须提供一个默认的构造方法,这也是和serializable接口的一个区别。不提供默认构造方法会抛出no
valid constructor错误信息。)
下面提供一个简单的例子:
Student是实现了Externalizable接口的可序列化类,并且显式提供了一个默认构造方法。
- public class Student implements Externalizable{
- private String name;
- private String password;
- public Student(String name ,String password) {
- this.name = name;
- this.password = password;
- }
- public Student() {
- System.out.println("default constructor is called");
- }
- public String getName() {
- return name;
- }
- public String getPassword() {
- return password;
- }
- @Override
- public void writeExternal(ObjectOutput out) throws IOException {
- System.out.println("writeExternal method is called");
- out.writeObject(name); // write name
- /* encrypt password */
- out.writeObject("***" + password); // write password
- }
- @Override
- public void readExternal(ObjectInput in) throws IOException,
- ClassNotFoundException {
- System.out.println("readExternal method is called");
- /* read in order */
- this.name = (String)in.readObject();
- this.password = ((String)in.readObject()).substring(3); // decrypt password
- }
- @Override
- public String toString() {
- return "name:" + name + ",password:" + password;
- }
- }
public class Student implements Externalizable{
private String name;
private String password;
public Student(String name ,String password) {
this.name = name;
this.password = password;
}
public Student() {
System.out.println("default constructor is called");
}
public String getName() {
return name;
}
public String getPassword() {
return password;
}
@Override
public void writeExternal(ObjectOutput out) throws IOException {
System.out.println("writeExternal method is called");
out.writeObject(name); // write name
/* encrypt password */
out.writeObject("***" + password); // write password
}
@Override
public void readExternal(ObjectInput in) throws IOException,
ClassNotFoundException {
System.out.println("readExternal method is called");
/* read in order */
this.name = (String)in.readObject();
this.password = ((String)in.readObject()).substring(3); // decrypt password
}
@Override
public String toString() {
return "name:" + name + ",password:" + password;
}
}
测试类:
- public class Demo {
- public static void main(String[] args) throws Exception {
- Student stu = new Student("benson", "21345");
- serialize(stu);
- deSerialize();
- }
- private static void serialize(Student stu) throws FileNotFoundException,
- IOException {
- OutputStream os = new FileOutputStream(new File("user.bin"));
- ObjectOutputStream oos = new ObjectOutputStream(os);
- oos.writeObject(stu);
- oos.close();
- }
- private static void deSerialize() throws FileNotFoundException,
- IOException, ClassNotFoundException {
- InputStream is = new FileInputStream(new File("user.bin"));
- ObjectInputStream ois = new ObjectInputStream(is);
- Student user = (Student) ois.readObject();
- ois.close();
- System.out.println(user);
- }
- }
public class Demo {
public static void main(String[] args) throws Exception {
Student stu = new Student("benson", "21345");
serialize(stu);
deSerialize();
}
private static void serialize(Student stu) throws FileNotFoundException,
IOException {
OutputStream os = new FileOutputStream(new File("user.bin"));
ObjectOutputStream oos = new ObjectOutputStream(os);
oos.writeObject(stu);
oos.close();
}
private static void deSerialize() throws FileNotFoundException,
IOException, ClassNotFoundException {
InputStream is = new FileInputStream(new File("user.bin"));
ObjectInputStream ois = new ObjectInputStream(is);
Student user = (Student) ois.readObject();
ois.close();
System.out.println(user);
}
}
Student在序列化的时候对密码字段进行了简单的加密,反序列化时进行了解密。
打印结果如下:
- writeExternal method is called
- default constructor is called
- readExternal method is called
- name:benson,password:21345
假如在网络上传输该对象的二进制时被黑客截获,虽然他可以利用公开的序列化格式对截获的信息进行分析,但是密码加过密,因此加大了黑客解密的难度。如该文件内容:
user.bin:
顶
踩
评论