参考: https://blog.csdn.net/qq_27093465/article/details/78544505
参考: http://www.cnblogs.com/liango/p/7143848.html
transient 参考: http://www.cnblogs.com/lanxuezaipiao/p/3369962.html
HashMap 私有writeObject 参考: http://www.a-site.cn/article/140346.html
序列化:就是将Java 对象以一定的规则转化为字节序列的过程
反序列化:就是将字节序列还原为Java 对象的过程
问题:
1. java 如何实现序列化和反序列化
实体类实现serialiezable 接口,用ObjectInputStream 的 writeObject(obj) 序列化,ObjectInputStream的readObject(obj) 反序列化
2.静态属性能否被序列化
不能,静态属性不写入序列化,可以测试发现,当把对象写入序列化后,然后改把类中静态变量的值,然后再将对象反序列化打印,发现对象中的静态变量,是刚才修改过的值,根据没有固定的写入序列化文件中
3.serialVersionUID 有何作用
这个属性,就是一个类标识的意思,序列化的时候,如果加了这个标识,然后反序列的时候,就会去校验文件中对象的序列化属性,如果不正确,Java 就认为不是同一个类型,就出报 InvalidClassException ,所以实现serializable 最好加上这个属性,不然不小心修改这个值程序出错,都不知道在什么地方,(经过测试发现,如果将在对象序列化之前,去掉类中的serialVersionUID标识,然后序列化,然后再将对象的serialVersionUID 恢复,这个时候在反序列化,就会报InvalidClassException 异常,提示 serialVersionUID 不相同,是因为如果序列化时,如果类中没有定义具体的值,Java在执行的时候,会默认加上一个serialVersionUID,然后在反序列化时不相同就会报错)
4.transient 修饰的变量能否被序列化,这个关键字的意义
transient 修饰的变量不能被序列化,
java的transient关键字为我们提供了便利,你只需要实现Serilizable接口,将不需要序列化的属性前添加关键字transient,序列化对象的时候,这个属性就不会序列化到指定的目的地中。
实际开发过程中,我们常常会遇到这样的问题,这个类的有些属性需要序列化,而其他属性不需要被序列化,打个比方,如果一个用户有一些敏感信息(如密码,银行卡号等),为了安全起见,
不希望在网络操作(主要涉及到序列化操作,本地序列化缓存也适用)中被传输,这些信息对应的变量就可以加上transient关键字。换句话说,这个字段的生命周期仅存于调用者的内存中而不会写到磁盘里持久化。
5.HashMap等一些类 为什么将 wirteObject 和 readObject 方法,私有化
一般我们序列化都是调用ObjectInputStream 的 writeObject(obj) 序列化,ObjectInputStream的readObject(obj) 反序列化,但是有些类自己实现了自己的wirteObject 和 readObject方法,但是私有化了,其实我们通过调用ObjectInputStream 的 writeObject(obj) 方法时,会去查相关类有没有自己实现wrterObject 方法,如果有是实现,最后执行自己的writeObject 方法
{@see ObjectOutputStream} 的 writeObject 方法可看出,如果 其他类有自己的writeObject 方法,会调用的自己的writeObject 方法,wirteObject0 -> writeOrdinaryObject -> writeSerialData() 最后执行自己的writeObject 方法
package test.io.io;
import java.io.Serializable;
/**
* 测试Java 的序列化接口,和反序列化
* 测试 ObjectInputStream 和 ObjectOutputStream 写入序列化数据,和读取序列化数据
* 实体类必须实现 Serializable 接口
* 静态对象没有被写入序列化对象
* 参考:https://blog.csdn.net/qq_27093465/article/details/78544505
* 参考:http://www.cnblogs.com/liango/p/7143848.html
*
* TODO 3 个问题:
* 1. 如何实现序列化和反序列化 实体类实现serialiezable 接口,用ObjectInputStream 的 writeObject(obj) 序列化,ObjectInputStream的readObject(obj) 反序列化
* 2. 静态属性能否被序列化 否
* 3. serialVersionUID 有何作用 这个属性,就是一个类标识的意思,序列化的时候,如果加了这个标识,然后反序列的时候,就会去校验文件中对象的序列化属性,如果不正确,Java 就认为不是同一个类型,就出报 InvalidClassException ,
* 所以实现serializable 最好加上这个属性,不然不小心修改这个值程序出错,都不知道在什么地方
* 4. transient 修饰的变量能否被序列化 否
* @author 12198
*
*/
public class TestPeople implements Serializable{
/**
*
*/
private static final long serialVersionUID = 1L;
private int i;
private String name;
private String age;
private String text;
public static String t1 = "386";
transient private String tip;
public TestPeople() {
super();
// TODO Auto-generated constructor stub
}
/**
* @param i
* @param name
* @param age
* @param text
*/
public TestPeople(int i, String name, String age, String text,String tip) {
super();
this.i = i;
this.name = name;
this.age = age;
this.text = text;
this.tip = tip;
}
@Override
public String toString() {
return "TestSerializable [i=" + i + ", name=" + name + ", age=" + age + ", text=" + text + ", t1 =" + t1 + ",tip =" + tip + "]";
}
public int getI() {
return i;
}
public void setI(int i) {
this.i = i;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAge() {
return age;
}
public void setAge(String age) {
this.age = age;
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
}
测试类
package test.io.io;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
/**
* 测试 序列化接口,
* @author 12198
*
*/
public class TestSerialize {
public static void main(String[] args) {
String fileName = "D://object.txt";
TestPeople ts = new TestPeople(3, "kt", "18", "zhang","tip");
// serialize(ts, fileName);//测试序列化
TestPeople.t1 = "26";//如果 t1 会变写入文件,此时修改类中的t1,应该不会改变文件中的对象
reSerialize(fileName);
}
public static void serialize(TestPeople ts,String fileName) {
try {
ObjectOutputStream outputStream = new ObjectOutputStream(new FileOutputStream(fileName));
outputStream.writeObject(ts);//序列化写入文件中
outputStream.close();
System.out.println("序列化成功");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static void reSerialize(String fileName){
ObjectInputStream inputStream;
try {
inputStream = new ObjectInputStream(new FileInputStream(fileName));
TestPeople rts = (TestPeople)inputStream.readObject();//反序列化读取
inputStream.close();
System.out.println("反序列化成功");
System.out.println(rts.toString());//然而读取出来的t1 却是 26,说明静态对象没有被写入序列化文件
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}