1

虽是读书笔记,但是如转载请注明出处 http://segmentfault.com/blog/exploring/
.. 拒绝伸手复制党


一个问题:

在阅读HashMapTreeMap的源码过程中,发现了一个奇怪的事情: 这些类执行了Serializable接口,却在关键地方,比如hashmap将存储数据的table 数组声明为transient. 这是何意?

stackoverflow 查了一下,大概有两个原因。
1.transient 是表明该数据不参与序列化。因为 HashMap 中的存储数据的数组数据成员中,数组还有很多的空间没有被使用,没有被使用到的空间被序列化没有意义。所以需要手动使用 writeObject() 方法,只序列化实际存储元素的数组。
2. 由于不同的虚拟机对于相同 hashCode 产生的 Code 值可能是不一样的,如果你使用默认的序列化,那么反序列化后,元素的位置和之前的是保持一致的,可是由于 hashCode 的值不一样了,那么定位函数 indexFor()返回的元素下标就会不同,这样不是我们所想要的结果.

图片描述


Java对象序列化

对象 ----- 字节流 ----- 文件

什么是对象序列化:

Java 平台允许我们在内存中创建可复用的 Java 对象,但一般情况下,只有当 JVM 处于运行时,这些对象才可能存在,即,这些对象的生命周期不会比 JVM 的生命周期更长。但在现实应用中,就可能要求在 JVM 停止运行之后能够保存 (持久化) 指定的对象,并在将来重新读取被保存的对象。Java 对象序列化就能够帮助我们实现该功能。

使用 Java 对象序列化,在保存对象时,会把其状态保存为一组字节,在未来,再将这些字节组装成对象。必须注意地是,对象序列化保存的是对象的 "状态",即它的成员变量。由此可知,对象序列化不会关注类中的静态变量。

除了在持久化对象时会用到对象序列化之外,当使用 RMI(远程方法调用),或在网络中传递对象时,都会用到对象序列化。

一个对象能够序列化的前提是实现`Serializable`接口,  `Serializable` 接口没有方法,更像是个标记。有了这个标记的 Class 就能被序列化机制处理。使用 `ObjectInputStream` 和 `ObjectOutputStream` 进行对象的读写。
    class User implements Serializable{
    private static final long serialVersionUID = 201322060620L;
    private String username;
    private transient String passwd;

    public String getUsername(){
        return username;
    }
    public void setUsername(String username){
        this.username = username;
    }
    public String getPasswd(){
        return this.passwd;
    }
    public void setPasswd(String passwd){
        this.passwd = passwd;
    }
}

public class TransientTest {
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        User user = new User();
        user.setUsername("GSM");
        user.setPasswd("1010");

        System.out.println("read before Serializable: ");
        System.out.println("username: " + user.getUsername());
        System.err.println("password: " + user.getPasswd());

        try{
            ObjectOutputStream os = new ObjectOutputStream(
                    new FileOutputStream("F:/user.txt"));
            os.writeObject(user);//将User对象写入文件
            os.flush();
            os.close();
        }catch(FileNotFoundException e){
            e.printStackTrace();
        }catch(IOException e){
            e.printStackTrace();
        }

        try {
            ObjectInputStream is = new ObjectInputStream(
                    new FileInputStream(
                    "F:/user.txt"));
            user = (User) is.readObject(); // 从流中读取User的数据
            is.close();

            System.out.println("\nread after Serializable: ");
            System.out.println("username: " + user.getUsername());
            System.err.println("password: " + user.getPasswd());

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

}

user.txt 即 user对象保存到文件的内容是二进制的串,16进制查看:
user.txt
文件一共63B
想更一进步的支持我,请扫描下方的二维码,你懂的~
图片描述


SecondLife
1.9k 声望252 粉丝