java集合学习之List(一)序列化Serializable接口

 今天看了下了ArrayList的实现的源码,引申出来一点关于序列化,Random类,Atomic(Long)类,还有LinkedList的一些知识。

 首先ArrayList继承了AbstractList类,实现了List,RandomAccess,Cloneable以及Serializable接口。

 下面先来看一下Serializable接口,即序列化接口:

 首先看一下什么是序列化:序列化的定义是一种将对象以一连串的字节描述的过程,在java中万事万物皆对象,在分布式环境中经常需要将对象从一段网络传到另一端网络。

 来想下如果不使用序列化来传输对象会怎么样,结果自然是会报错。运行时报错:java.io.NotSerializableException,原因就是没有实现序列化接口。可是为什么要序列化呢,不能像在内存一样把对象作为参数传递呢?我再百度贴吧尚学堂吧看到一个解释感觉很有道理,引用过来:

 这里首先要确定一件事,内存中将对象作为参数传递其实只是传递对象的引用(指针)。就像是继承一样,并非是将父类对象保存在子类对象之中,而是子类对象包含了父类对象的引用,在java内部继承是通过隐式的组合实现的。子类对象中会保存一个实例对象的引用super,引用指向父类。实际的方法调用中,java会优先在当前类对象中寻找名称相同的方法,如果没有,会根据super引用到父类对象中去寻找,所以,如果父类方法在子类中得到了重写,java会调用子类的方法,而不会调用被重写的父类的方法,这也是多态的实现机制。

 所以,内存中传来传去的都是地址,如果直接将其存库,然后内存经过变化,取出来的引用肯定是变了,而java的优势是跨平台,在分布式的环境中,传递对象是非常普遍的,既然涉及到了传输,势必有相应的协议,序列化就是为了解决这个问题而出来的。 完。

 现在几乎所有的应用程序都涉及网络I/O和磁盘I/O,而数据传输时都是以字节为单位的,所以所有的数据都必须能够序列化为字节。在Java中数据要被序列化为字节流,存储在文件中或在网络上传输,必须继承Serializable接口。

 序列化的用处:永久性保存对象,保存对象的字节序列到本地文件或者数据库中、通过序列化以字节流的形式使对象在网络中进行传递和接收、通过序列化在进程之前传递对象。

 然后看一下Serializable接口的声明:public interface Serializable {},由此可见序列化接口没有方法或者是字段,所以更像是一个标志,标识可序列化。首先来看写一个序列化的例子:就用ArrayList来作为对象

 /**
         * 序列化
         */
        FileOutputStream fileOutputStream = new FileOutputStream("d:/serialzation.out");
        ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream);
        List list = new ArrayList();
        for(int i=0;i<1000;i++){
            list.add(i);
        }
        objectOutputStream.writeObject(list);
        objectOutputStream.flush();
        objectOutputStream.close();
        fileOutputStream.close();
        
        FileInputStream fileInputStream = new FileInputStream("d:/serialzation.txt");
        ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream);
        List lsit = (List) objectInputStream.readObject();
        System.out.println(lsit);
        fileInputStream.close();
        objectInputStream.close();

代码中ObjectOutputStream把list输出成Byte流,并存到serialzation.out文件中。

另外值得注意的是:在序列化过程中标有transient 关键字的变量和static变量是不会被序列化的,这个可以自己写个代码是实现下看看

还有,当我们实现序列化接口的时候,编译器会提示生成一个serialVersionUID,这个UID的作用是用来标识这个对象,如果不写这个UID,当你的对象的字段增加或者更改时,就会报错java.io.InvalidClassException,因为不实现定义UID,jvm就会自动生成一个隐形的UID,当你的属性字段变化的时候,UID也跟着变化,序列化后的UID和变化后的UID对应不起来,就会导致反序列化失败,当声明了UID后,即使字段改变,UID还是不会改变,反序列化还是会成功,即使你的属性值发生了变化,反序列化之后的对象的值,还是改变之前的值,例如:user的name="小可爱",当序列化User对象之后,将User的name改变成了"不可爱",如何再把user对象反序列化,得到的name还会是小可爱。

然后序列化之后的字节码文件.....还有待描述。百度到某个博客意思就是,当序列化的时候,二进制流中按照:当前类描述、当前类属性描述、超类描述、超类属性描述、超超类属性描述、超类属性值描述、子类属性值描述进行存储,即:类描述是从下到上,类属性描述是从上到下。俩个是反着来的。

链接如下:http://blog.csdn.net/morethinkmoretry/article/details/5929345



你可能感兴趣的:(java集合)