了解 ArrayList 源码(二)

package list;



//在ArrayList 源码中有这样的代码
/*
 * private void writeObject(java.io.ObjectOutputStream s)
        throws java.io.IOException{
        // Write out element count, and any hidden stuff
        int expectedModCount = modCount;
        s.defaultWriteObject();

        // Write out size as capacity for behavioural compatibility with clone()
        s.writeInt(size);

        // Write out all elements in the proper order.
        for (int i=0; i<size; i++) {
            s.writeObject(elementData[i]);
        }

        if (modCount != expectedModCount) {
            throw new ConcurrentModificationException();
        }
    }
    private void readObject(java.io.ObjectInputStream s)
        throws java.io.IOException, ClassNotFoundException {
        elementData = EMPTY_ELEMENTDATA;

        // Read in size, and any hidden stuff
        s.defaultReadObject();

        // Read in capacity
        s.readInt(); // ignored

        if (size > 0) {
            // be like clone(), allocate array based upon size not capacity
            ensureCapacityInternal(size);

            Object[] a = elementData;
            // Read in all elements in the proper order.
            for (int i=0; i<size; i++) {
                a[i] = s.readObject();
            }
        }
    }

    这是实现Serialiazable接口,并且重写readObject()和writeObject();在实际序列化的时候,会利用反射最终调用到你重写的
  writeObject和readObject 来序列化。现在这么一个问题:既然transient 修饰了elementData为什么还会重写呢?
  下面解答:
  首先看一看transient关键字的作用
  我们都知道只要一个类实现了serializable接口,这个类的对象就可以被序列化。然而在实际开发中,我们可能并不需要某些字段的序列化,
  所以就可以用transient修饰字段。比如密码。那就是说,这个字段只存在于调用者的内存中而不会被写入磁盘中被持久化。
  其次的明白序列化的流程
  要序列化一个对象,必须要将其与一个输入输出流联系起来。输出流以保存其状态,输入流恢复其状态。在序列化和反序列化的过程中必须使用下列
  准确签名来实现特殊方法。
  private void writeObiect(java.io.ObjectOutputStream s)throws java.io.IOException
  private void readObject(java.io.ObjectInputStream s)throws java.io.IOException ClassNotFoundException
  仔细观察源码可以发现,s.writeObjec(elementData[i])达到向输出流写入对象的目的。
  private 那么时候调用呢?
  ObjectOutputStream会调用这个类的writeObject方法进行序列化,ObjectInputStream会调用相应的readObject方法进行反序列化。
  那么ObjectOutputStream 怎么知道这个类重写了readObject()方法呢?反射!

  这时我可以说刚开始问题的答案了:ArrayList 其实是用数组实现的,明白他的扩容机制后便可以知道,它的容量是大于实际存储对象的个数的。
  如果说直接序列化的话,就会造成空间浪费。所以会在writeObject()中手动序列化。这样我们就序列化的是实际存储的对象元素。


*/
import java.io.File;
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;

public class AnimalSerializable implements Serializable{
private static final long serialVersionUID = -7461498806905104482L;

    public AnimalSerializable() {

    }

    public AnimalSerializable(int age, String name){
        this.age = age;
        this.name = name;
    }

    private  int age ;
    private  String name;

      private void writeObject(java.io.ObjectOutputStream s){
          try {
            s.writeObject(name);
            s.writeObject(age);
            System.out.println("重写了writeObject");
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
      }
      private void readObject(java.io.ObjectInputStream s){
          try {
            name = (String) s.readObject();
            age = (int) s.readObject();
            System.out.println("重写了 readObject");
        } catch (ClassNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
      }


    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;
    }

    @Override
    public String toString() {
        return "AnimalSerializable [age=" + age + ", name=" + name + "]";
    }

    public static void main(String[] args) {
        AnimalSerializable animal = new AnimalSerializable(10, "xiaohong");

        File file = new File("D:/test.txt");
        if(!file.exists()){
            try {
                file.createNewFile();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }

        try {
            ObjectOutputStream output = new ObjectOutputStream(new FileOutputStream(file));
            output.writeObject(animal);

            ObjectInputStream input = new ObjectInputStream(new FileInputStream(file));
            AnimalSerializable anima = (AnimalSerializable) input.readObject();
            System.out.println(anima.toString());
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值