java序列化

学习多篇java序列化的文章,抽取出对理解有帮助的内容:

Java中,一切都是对象,在分布式环境中经常需要将Object从这一端网络或设备传递到另一端。这就需要有一种可以在两端传输数据的协议。
Java序列化机制就是为了解决这个问题而产生。Serialization(序列化)是一种将对象以一连串的字节描述的过程;反序列化deserialization是一种将这些字节重建成一个对象的过程。是为了保存在内存中的各种对象的状态,并且可以把保存的对象状态再读出来。
Java程序必须要运行在Java虚拟机中,那么在同一个Java虚拟机进程中,换句话说是在同一快内存空间里面,什么地方需要用此对象,直接传递该对象的引用就可以了,我们想调某一个对象的方法,通过该对象的引用就可以了,传过去就可以了;对象的序列化技术,实现的手段是通过Object流,在不同JVM之间,可以通过对象序列化,将此对象序列化之后得到一些“内容”,通过网络传输这部分“内容”,从一个JVM上将一个对象序列化之后传过来,到另一个JVM再通过反序列化在内存中“造出一个对象出来”,这个对象和你序列化之前的JVM的对象是一样的。
对象序列化就是将一个对象转化成流,用于保存到文件或通过网络在另一端重新生成此对象。使用sterilization,你可以很容易实现所谓的“lightweight persistence”(轻量级持久化),让对象的生命周期超越程序的生命周期。在没有序列化前,每个保存在堆(Heap)中的对象都有相应的状态(state),即实例变量(instance ariable)。

序列化的过程就是 object->(按一定顺序拆分)write->bytes->(按拆分顺序组装)read->object的过程
为了序列化一个对象,你需要用到输出流OutputStream,OutputStream必需被放入特殊的称作ObjectOutputStream的序列化流中。然后,你只需要调用方法writeObject()来序列化对象并发送到输出流中。为了反序列化一个对象,你需要把InputStream转化进ObjectInputStream中,然后调用readObject()方法。和往常一样,你需要得到一个对象的引用,所以你也得构造所需类型的对象的class cast。

注意事项:
1、序列化机制,只对对象的状态进行保存,只保存对象的类型信息,属性的类型信息和属性值,不记录方法
2、当一个父类实现序列化,子类自动实现序列化,不需要显式实现Serializable接口;
3、当一个对象的实例变量引用其他对象,序列化该对象时也把引用对象进行序列化;
4、并非所有的对象都可以序列化,比如:
1.安全方面的原因,比如一个对象拥有private,public等field,对于一个要传输的对象,比如写到文件,或者进行rmi传输 等等,在序列化进行传输的过程中,这个对象的private等域是不受保护的。
2. 资源分配方面的原因,比如socket,thread类,如果可以序列化,进行传输或者保存,也无法对他们进行重新的资源分配,而且,也是没有必要这样实现。
5、当一个对象被序列化时,只保存对象的非静态成员变量,不能保存任何的成员方法和静态的成员变量。
6、如果一个对象的成员变量是一个对象,那么这个对象的数据成员也会被保存。
7、在Java规范中,一个类是否能序列化,不但取决于这个类是否实现Serializable接口,还取决于这个类中的属性是否可序列化。String类是可序列化的(继承了Serializable接口且它的属性都是可序列化的),而像 int这样的基本数据类型在Java中被看成是可序列化的。
8、在Java doc中明确指出,如果一个类继承了一个非Serializable类时,如果想在序列化中保存父类的属性,则需要实现额外的代码显式地存储父类的属性值。
9、如果一个可序列化的对象包含对某个不可序列化的对象的引用,那么整个序列化操作将会失败,并且会抛出一个NotSerializableException。我们可以将这个引用标记为transient,那么对象仍然可以序列化。还有我们对某个对象进行序列化时候,往往对整个对象全部序列化了,比如说类里有些数据比较敏感,不希望序列化,一个方法可以用transient来标识,另一个方法我们可以在类里重写readObject,writeObject:
private void writeObject(java.io.ObjectOutputStream out)
throws IOException
private void readObject(java.io.ObjectInputStream in)
throws IOException, ClassNotFoundException;

用transient来标识:

package com.sertest;
import java.io.Serializable;
import java.io.FileOutputStream;
import java.io.ObjectOutputStream;
import java.io.FileInputStream;
import java.io.ObjectInputStream;
public class TestSerial implements Serializable{
private String name;
private int age;
transient String pwd;//不序列化该变量
public int getAge(){
return age;
}
public void setAge(int age){
this.age=age;
}
public String getName(){
return name;
}
public void setName(String name){
this.name=name;
}
public String getPWD(){
return pwd;
}
public void setPWD(String pwd){
this.pwd=pwd;
}
public String toString() {
return "This is a serializable test!";
}

public void doSomeWork() {
System.out.println("hello");
}
public static void main(String[] args) throws Exception{
TestSerial ts=new TestSerial();
ts.setAge(10);
ts.setName("guest");
ts.setPWD("111111");
FileOutputStream fos=new FileOutputStream("tefile");
ObjectOutputStream oos=new ObjectOutputStream(fos);
oos.writeObject(ts);
oos.close();
fos.close();

FileInputStream fis = new FileInputStream("tefile");
ObjectInputStream oin = new ObjectInputStream(fis);
TestSerial ts1 = (TestSerial) oin.readObject();
System.out.println("age="+ts1.age);
System.out.println("name="+ts1.name);
System.out.println("pwd="+ts1.pwd);
}
}


重写两个方法:

package com.sertest;

import java.io.Serializable;
import java.io.FileOutputStream;
import java.io.ObjectOutputStream;
import java.io.FileInputStream;
import java.io.ObjectInputStream;
import java.io.IOException;
public class Serialtest{
public static void main(String[] args) throws Exception{
PersonInfo ts=new PersonInfo();
ts.setAge(10);
ts.setName("guest");
ts.setPWD("111111");
FileOutputStream fos=new FileOutputStream("tefile");
ObjectOutputStream oos=new ObjectOutputStream(fos);
oos.writeObject(ts);
oos.close();
fos.close();

FileInputStream fis = new FileInputStream("tefile");
ObjectInputStream oin = new ObjectInputStream(fis);
PersonInfo ts1 = (PersonInfo) oin.readObject();
System.out.println("PersonInfo"+ts1);
//System.out.println("age="+ts1.age);
//System.out.println("name="+ts1.name);
//System.out.println("pwd="+ts1.pwd);
}
}
class PersonInfo implements Serializable{
public String name;
public int age;
String pwd;
public int getAge(){
return age;
}
public void setAge(int age){
this.age=age;
}
public String getName(){
return name;
}
public void setName(String name){
this.name=name;
}
public String getPWD(){
return pwd;
}
public void setPWD(String pwd){
this.pwd=pwd;
}
public String toString() {
return "This is a serializable test!"+"name="+name+";age="+age+";pwd="+pwd;
}
private void writeObject(java.io.ObjectOutputStream oos) throws IOException
{
oos.writeInt(age);
oos.writeUTF(name);
System.out.println( " Write Object " );
}
private void readObject(java.io.ObjectInputStream ois) throws IOException
{
this.age = ois.readInt();
this.name = ois.readUTF();
System.out.println( " Read Object " );
}
public void doSomeWork() {
System.out.println("hello");
}
}




2、序列化算法一般会按步骤做如下事情:

◆将对象实例相关的类元数据输出。

◆递归地输出类的超类描述直到不再有超类。

◆类元数据完了以后,开始从最顶层的超类开始输出对象实例的实际数据值。

◆从上至下递归输出实例的数据

3、序列化的时机:
a)当你想把的内存中的对象状态保存到一个文件中或者数据库中时候;
b)分布式环境中传送对象
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值