serializable

时间:2024-08-11 13:49:33编辑:花茶君

java序列化--java.io.Serializable接口解析

  使用java以来 序列化随处可见 至于为什么要用序列化 序列化能解决什么问题 作为一个普通的码农 一般不怎么会去深入研究 由于最近在看mina和公司内部涉及到nio框架的一些源码 里面涉及到hession java这两种序列化 至于hession序列化为什么会诞生以及在apache项目中使用如此广泛 以及java本身序列化存在哪些缺陷 甚是不解 为了解答上面抛出来的疑惑 以及进一步了解java的序列化机制 这里开个小头 从java的序列化接口Serializable开始说起   jdk包里的Serializable接口的注释主要说明了以下几点    类通过实现Serializable接口来启用序列化 否则该类的任何状态将无法被序列化 同时也无法用于反序列化    若继承的父类没有实现Serializable接口 但是又想让子类可序列化 有三个注意事项   a) 子类实现Serializable接口   b) 子类必须有可访问的无参构造方法 用于保存和恢复父类的public或protected或同包下的package字段的状态 否则在序列化或反序列化时会抛出RuntimeException异常   c) 对于序列化后的子类 在进行反序列化时 理论上无法初始化父类中private(不可访问)对象变量的状态或值    在对可序列化类中的属性进行序列化时 如果遇到不可序列化的对象变量 此时会针对不可序列化的类抛出NotSerializableException异常    对于可序列化的非数组类 强烈建议显示声明static型 long型 final型serialVersionUID字段用于标识当前序列化类的版本号 否则在跨操作系统 跨编译器之间进行序列化和反序列化时容易出现InvalidClassException异常    对于可序列化类中的static transient对象变量 在序列化时无法保存其状态或值 static对象变量在反序列化时取得的值为当前jvm中对应类中对应static变量的值 而transient(瞬态)关键字则一般用于标识那些在序列化时不需要传递的状态变量   简单的测试代码    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 io Serializable    /** * 序列化测试 * * @author sume * */ public class SerializableImpl implements Serializable {    private static final long serialVersionUID = L    static String staticVal = static transient String transientVal = transient String val = val    /** * main */ public static void main(String[] args) throws FileNotFoundException IOException ClassNotFoundException { // 序列化 SerializableImpl sila = new SerializableImpl() ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream( Serializable txt )) objectOutputStream writeObject(sila ) objectOutputStream close()    // 反序列化 SerializableImpl staticVal = static ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream( Serializable txt )) SerializableImpl sila = (SerializableImpl) objectInputStream readObject() objectInputStream close()    // 比较各个属性的值 System out println(sila staticVal) System out println(sila transientVal) System out println(sila val) } }输出结果 static null val 从输出结果可以看出    反序列化后类中static型变量staticVal的值为当前jvm中对应static变量的值 为 static 而不是序列化时的值 static    transient关键字标识的变量的状态并没有在序列化中被保存 因此反序列化后   transientVal变量的值为null    第三个为常见的对象状态在序列化和反序列化过程中的传递 lishixinzhi/Article/program/Java/hx/201311/26282


parcelable和serializable的区别

Parcelable和Serializable的作用、效率、区别及选择:
1、作用
Serializable的作用是为了保存对象的属性到本地文件、数据库、网络流、rmi以方便数据传输,当然这种传输可以是程序内的也可以是两个程序间的。而Android的Parcelable的设计初衷是因为Serializable效率过慢,为了在程序内不同组件间以及不同Android程序间(AIDL)高效的传输数据而设计,这些数据仅在内存中存在,Parcelable是通过IBinder通信的消息的载体。
从上面的设计上我们就可以看出优劣了。

2、效率及选择
Parcelable的性能比Serializable好,在内存开销方面较小,所以在内存间数据传输时推荐使用Parcelable,如activity间传输数据,而Serializable可将数据持久化方便保存,所以在需要保存或网络传输数据时选择Serializable,因为android不同版本Parcelable可能不同,所以不推荐使用Parcelable进行数据持久化

3、编程实现
对于Serializable,类只需要实现Serializable接口,并提供一个序列化版本id(serialVersionUID)即可。而Parcelable则需要实现writeToParcel、describeContents函数以及静态的CREATOR变量,实际上就是将如何打包和解包的工作自己来定义,而序列化的这些操作完全由底层实现。
Parcelable的一个实现例子如下
[java] view plaincopy
public class MyParcelable implements Parcelable {
private int mData;
private String mStr;

public int describeContents() {
return 0;
}

// 写数据进行保存
public void writeToParcel(Parcel out, int flags) {
out.writeInt(mData);
out.writeString(mStr);
}

// 用来创建自定义的Parcelable的对象
public static final Parcelable.Creator CREATOR
= new Parcelable.Creator() {
public MyParcelable createFromParcel(Parcel in) {
return new MyParcelable(in);
}

public MyParcelable[] newArray(int size) {
return new MyParcelable[size];
}
};

// 读数据进行恢复
private MyParcelable(Parcel in) {
mData = in.readInt();
mStr = in.readString();
}
}

从上面我们可以看出Parcel的写入和读出顺序是一致的。如果元素是list读出时需要先new一个ArrayList传入,否则会报空指针异常。如下:
list = new ArrayList();
in.readStringList(list);

PS: 在自己使用时,read数据时误将前面int数据当作long读出,结果后面的顺序错乱,报如下异常,当类字段较多时务必保持写入和读取的类型及顺序一致。
11-21 20:14:10.317: E/AndroidRuntime(21114): Caused by: java.lang.RuntimeException: Parcel android.os.Parcel@4126ed60: Unmarshalling unknown type code 3014773 at offset 164


4、高级功能上
Serializable序列化不保存静态变量,可以使用Transient关键字对部分字段不进行序列化,也可以覆盖writeObject、readObject方法以实现序列化过程自定义


、什么是java序列化,如何实现java序列化?或者请解 释Serializable接口的作用。

我们有时候将一个java 对象变成字节流的形式传出去或者从一个字节流中恢复成一个
java 对象,例如,要将java 对象存储到硬盘或者传送给网络上的其他计算机,这个过程
我们可以自己写代码去把一个java 对象变成某个格式的字节流再传输,但是,jre 本身
就提供了这种支持,我们可以调用OutputStream的writeObject方法来做,如果要让java
帮我们做,要被传输的对象必须实现serializable 接口,这样,javac 编译时就会进行特
殊处理,编译的类才可以被writeObject方法操作,这就是所谓的序列化。需要被序列化
的类必须实现Serializable 接口,该接口是一个mini 接口,其中没有需要实现的方法,
implements Serializable只是为了标注该对象是可被序列化的。
例如,在web 开发中,如果对象被保存在了Session 中,tomcat 在重启时要把Session
对象序列化到硬盘,这个对象就必须实现Serializable接口。如果对象要经过分布式系统
进行网络传输或通过rmi 等远程调用,这就需要在网络上传输对象,被传输的对象就必
须实现Serializable接口。
还有什么问题可以百度hi我


上一篇:有一点动心mv

下一篇:职业特工队