先新建一个java类:
class ObjectSearilizeTest{
private long id =1234;
private int num;
private String userName;
public static int TEST_CONTANT =1234;
private transient String cannotSee;
public void setId(long id) {
this.id = id;
}
public void setNum(int num) {
this.num = num;
}
public void setUserName(String userName) {
this.userName = userName;
}
public void setCannotSee(String cannotSee) {
this.cannotSee = cannotSee;
}
public long getId() {
return id;
}
public int getNum() {
return num;
}
public String getUserName() {
return userName;
}
public String getCannotSee() {
return cannotSee;
}
}
使用ObjectInput(Output)Stream序列化对象并反序列化之:
public static void main(String args[]){
OutputStream fileStream = null;
try {
fileStream = new FileOutputStream(file);
ObjectOutputStream outputStream = new ObjectOutputStream(fileStream);
ObjectSearilizeTest test = new ObjectSearilizeTest();
test.setId(1234L);
test.setCannotSee("can u see me");
test.setNum(1);
test.setUserName("songjing");
outputStream.writeObject(test);
outputStream.close();
ObjectInputStream inputStream = new ObjectInputStream(new FileInputStream(file)) ;
ObjectSearilizeTest.TEST_CONTANT =12345;
ObjectSearilizeTest outTest = (ObjectSearilizeTest) inputStream.readObject();
System.out.println("outTest.getId() = " + outTest.getId());
System.out.println("outTest.getUserName() = " + outTest.getUserName());
System.out.println("outTest.getCannotSee() = " + outTest.getCannotSee());
System.out.println("outTest.getNum() = " + outTest.getNum());
System.out.println("ObjectSearilizeTest.TEST_CONTANT = " + ObjectSearilizeTest.TEST_CONTANT);
} catch (Exception e) {
System.out.println("e = " + e);
//todo
}
}
你将看到的输出是:
e = java.io.NotSerializableException: com.taobao.cms.ObjectSearilizeTest
好,问题很明显,没有实现序列化接口,做如下改动即可:
class ObjectSearilizeTest implements Serializable
再看输出结果:
outTest.getId() = 1234
outTest.getUserName() = songjing
outTest.getCannotSee() = null
outTest.getNum() = 1
ObjectSearilizeTest.TEST_CONTANT = 12345
首先,可以看出带transient关键字的属性字段不会被序列化,输入为null而非“can u see me “
其次,static字段的TEST_CONTANT输出是12345而非1234,可见static字段在序列化时的特殊之处;
另外序列化对象如果添加唯一id:
private static final long serialVersionUID =1281778809001846002L;
可以校验版本一致性问题,以下是关于序列化id的一些文字解释,转载自http://sharajava.iteye.com/blog/102886
简单来说,Java的序列化机制是通过在运行时判断类的serialVersionUID来验证版本一致性的。在进行反序列化时,JVM会把传来的字节流中的serialVersionUID与本地相应实体(类)的serialVersionUID进行比较,如果相同就认为是一致的,可以进行反序列化,否则就会出现序列化版本不一致的异常。
当实现java.io.Serializable接口的实体(类)没有显式地定义一个名为serialVersionUID,类型为long的变量时,Java序列化机制会根据编译的class自动生成一个serialVersionUID作序列化版本比较用,这种情况下,只有同一次编译生成的class才会生成相同的serialVersionUID 。
如果我们不希望通过编译来强制划分软件版本,即实现序列化接口的实体能够兼容先前版本,未作更改的类,就需要显式地定义一个名为serialVersionUID,类型为long的变量,不修改这个变量值的序列化实体都可以相互进行串行化和反串行化。
另外,关于两个特殊的stream可参看官方api说明:
http://download.oracle.com/javase/6/docs/api/java/io/ObjectOutputStream.html
http://download.oracle.com/javase/6/docs/api/java/io/ObjectInputStream.html