static和transient变量序列化问题
来源:互联网 发布:mac淘宝卖家 编辑:程序博客网 时间:2024/06/16 20:42
看下面的代码:
1.Person.java
2.DataObject.java
3.运行以后发现上面的输出结果,我们说static变量不能被序列化,但是现在为什么我们看到的object和object2的状态却是连续的呢?
4.我们在最后添加上一些代码来继续这个问题:
看到什么了?
第一句:序列化以前的和序列化以后的不是同一个对象!这不是废话嘛,我们都知道!
第二句:竟然输出了true!
第三句:输出false,本来就应该是false才对嘛。看出点什么?难道object.p和object2.p本来就是同一个对象实例?可不是嘛!同一个JVM内部只会存在静态变量的一个实例,当然他们是一样的了。也就是说,object.p并没有被序列化,而只是存在于JVM内部,当反序列化的时候,JVM用的还是这一个实例,难怪他们会是一样的了!
其实第二句完全等价于:System.out.println(DataObject.p==DataObject.p);//true,这样就更好理解了!并且就算Person类没有实现Serializable接口,如果是静态的,照样能读出来,但是却不是序列化的原因!
5. 你也许要问了,如果JVM中没有这个静态实例会是怎么样的呢?下面我们就来看一看:
/*
打印输出:
构建一个Person对象
hello:world
*/
这回我们看得很清楚了,因为这个新启动的JVM内部并没有事先已经存在一个Person对象实例,所以当反序列化的时候,由于反序列化构建一个对象属于对类的主动使用,所以会对类进行初始化,对类的静态变量进行赋值,所以我们看到的是只是经过初始化以后的对象实例,而不是序列化以前的那个实例,因此也就无法保持状态的连续了!6.那么对于transient变量又是怎么样的呢?
我们修改代码:
运行以后发现输出:
/*
构建一个Person对象
序列化以前:why
Exception in thread "main" java.lang.NullPointerException
at Data2Object.toString(Data2Object.java:8)
at java.lang.String.valueOf(String.java:2827)
at java.lang.StringBuilder.append(StringBuilder.java:115)
at Data2Object.main(Data2Object.java:22)
*/
也就是说反序列化以后根本就找不到transient变量,因为transient根本就没有被序列化! 看一个序列化的例子:
country本身实现了Serializable接口,可以进行序列化,而其中的成员除了name都是static。为了在反序列化的时候得到Country里面的静态成员,就需要提供一个readResolve()方法,用它来返回Map里面的静态实例。
如果注释掉readResolve方法,那么将会反序列化出不同的对象出来。
1.Person.java
import java.io.*;class Person implements Serializable{ public String name; public Person(String name){ this.name=name; System.out.println("构建一个Person对象"); }}
2.DataObject.java
import java.io.*; public class DataObject implements Serializable { public static Person p=new Person("hello");//静态的 public Person p2=new Person("world");//非静态的 public String toString() { return p.name+":"+p2.name; } public static void main(String[] args) throws ClassNotFoundException,FileNotFoundException,IOException { DataObject object=new DataObject(); object.p.name="why"; System.out.println("序列化以前:"+object); //序列化以前:why:world ObjectOutputStream out=new ObjectOutputStream(new FileOutputStream("lql.out")); out.writeObject(object); ObjectInputStream in=new ObjectInputStream(new FileInputStream("lql.out")); DataObject object2=(DataObject)in.readObject(); System.out.println("序列化以后:"+object2); //序列化以后:why:world } }
3.运行以后发现上面的输出结果,我们说static变量不能被序列化,但是现在为什么我们看到的object和object2的状态却是连续的呢?
4.我们在最后添加上一些代码来继续这个问题:
System.out.println("object==object2?"+(object==object2)); //falseSystem.out.println("object.p==object2.p?"+(object.p==object2.p));//trueSystem.out.println("object.p2==object2.p2?"+(object.p2==object2.p2));//false
看到什么了?
第一句:序列化以前的和序列化以后的不是同一个对象!这不是废话嘛,我们都知道!
第二句:竟然输出了true!
第三句:输出false,本来就应该是false才对嘛。看出点什么?难道object.p和object2.p本来就是同一个对象实例?可不是嘛!同一个JVM内部只会存在静态变量的一个实例,当然他们是一样的了。也就是说,object.p并没有被序列化,而只是存在于JVM内部,当反序列化的时候,JVM用的还是这一个实例,难怪他们会是一样的了!
其实第二句完全等价于:System.out.println(DataObject.p==DataObject.p);//true,这样就更好理解了!并且就算Person类没有实现Serializable接口,如果是静态的,照样能读出来,但是却不是序列化的原因!
5. 你也许要问了,如果JVM中没有这个静态实例会是怎么样的呢?下面我们就来看一看:
import java.io.*;public class SerTest{public static void main(String[] args) throws ClassNotFoundException,FileNotFoundException,IOException { ObjectInputStream in=new ObjectInputStream(new FileInputStream("lql.out")); DataObject object2=(DataObject)in.readObject(); System.out.println(object2); } }
/*
打印输出:
构建一个Person对象
hello:world
*/
这回我们看得很清楚了,因为这个新启动的JVM内部并没有事先已经存在一个Person对象实例,所以当反序列化的时候,由于反序列化构建一个对象属于对类的主动使用,所以会对类进行初始化,对类的静态变量进行赋值,所以我们看到的是只是经过初始化以后的对象实例,而不是序列化以前的那个实例,因此也就无法保持状态的连续了!6.那么对于transient变量又是怎么样的呢?
我们修改代码:
import java.io.*; public class Data2Object implements Serializable { public transient Person p=new Person("hello") public String toString() { return p.name; } public static void main(String[] args) throws ClassNotFoundException,FileNotFoundException,IOException { Data2Object object=new Data2Object(); object.p.name="why"; System.out.println("序列化以前:"+object); ObjectOutputStream out=new ObjectOutputStream(new FileOutputStream("lql.out")); out.writeObject(object); ObjectInputStream in=new ObjectInputStream(new FileInputStream("lql.out")); Data2Object object2=(Data2Object)in.readObject(); System.out.println("序列化以后:"+object2); System.out.println("object==object2?"+(object==object2)); System.out.println("object.p==object2.p?"+(object.p==object2.p)); } }
运行以后发现输出:
/*
构建一个Person对象
序列化以前:why
Exception in thread "main" java.lang.NullPointerException
at Data2Object.toString(Data2Object.java:8)
at java.lang.String.valueOf(String.java:2827)
at java.lang.StringBuilder.append(StringBuilder.java:115)
at Data2Object.main(Data2Object.java:22)
*/
也就是说反序列化以后根本就找不到transient变量,因为transient根本就没有被序列化! 看一个序列化的例子:
import java.util.*;import java.io.*;public final class Country implements Serializable{ private static final Map INDEX=new HashMap(); public static final Country CANADA =new Country("CANADA"); public static final Country US=new Country("US"); public static final Country EN =new Country("EN"); public static final Country CHINA =new Country("CHINA"); private String name; private Country(String name){ this.name=name; INDEX.put(name,this); } private static Country lookup(String name){ return (Country)INDEX.get(name); } public String toString(){ return this.name; } private Object readResolve()throws ObjectStreamException{ Country c=lookup(name); return c; } public static void main(String rags[]){ System.out.println(Country.lookup("CHINA")); }}
country本身实现了Serializable接口,可以进行序列化,而其中的成员除了name都是static。为了在反序列化的时候得到Country里面的静态成员,就需要提供一个readResolve()方法,用它来返回Map里面的静态实例。
import java.util.*;import java.io.*;public final class SerTest{ public static void main(String rags[])throws Exception{ FileOutputStream fout=new FileOutputStream("test.out"); ObjectOutputStream oout=new ObjectOutputStream(fout); oout.writeObject(Country.CHINA); System.out.println(Country.CHINA.hashCode()); fout.close(); oout.close(); FileInputStream fin=new FileInputStream("test.out"); ObjectInputStream oin=new ObjectInputStream(fin); Country c=(Country)oin.readObject(); System.out.println(c.hashCode()); fin.close(); oin.close(); System.out.println(c==Country.CHINA); }}
如果注释掉readResolve方法,那么将会反序列化出不同的对象出来。
0 0
- static和transient变量序列化问题
- java序列化(transient和static修饰的变量的序列化实现)
- Java 序列化static变量问题
- java序列化和transient
- java序列化与反序列化中transient和static成员剖析
- java transient(不会序列化)、static关键字的作用
- java 序列化和transient的用法
- Java 对象序列化和transient 作用
- java 对象序列化 与 静态变量 及 transient
- java transient和static 解析
- transient与序列化
- java transient 序列化
- transient与序列化
- transient ,序列化
- 序列化之-----transient
- transient与序列化
- 序列化关键字transient
- Java序列化之排除被序列化字段(transient/静态变量)
- Tomcat发布
- [从头学数学] 第281节 [计算几何] 路径分解
- Android 开源项目源码解析 -->PhotoView 源码解析(七)
- CentOS中解决root用户无法登陆ftp传输文件的问题
- android中popupwindow弹出后,屏幕背景变成半透明
- static和transient变量序列化问题
- React学习笔记--通过Redux 的三个基本原则来理解Redux
- Spring Boot CLI DEMO Setup
- 开机修改CentOS7密码
- Hadoop集群中Hbase的介绍、安装、使用
- shader实现图片阴影
- 详解js闭包
- Spring中的所有路径匹配问题总结
- 自动蓄水系统 java小程序(简单小插件开发)