java序列化机制 Serialize
接口
序列化:把对象转换为字节序列的过程称为对象的序列化。
反序列化:把字节序列恢复为对象的过程称为对象的反序列化。
java序列化得主要目的 :
- 网络传输
- 对象持久化
java序列化对象代码 :
import java.io.Serializable;
public class Person implements Serializable {
private static final long serialVersionUID = 1L;
private String name;
private int id;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
@Override
public String toString() {
return "Person [name=" + name + ", id=" + id + "]";
}
}
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
public class SerilizedDemo {
public static void main(String[] args) {
deSerializeMethod();
}
/**
* 序列化方法
*/
private static void serializeMethod() {
try {
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(new File("Person")));
Person person = new Person();
person.setId(1);
person.setName("wang");
out.writeObject(person);
out.close();
System.out.println("序列化成功");
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 反序列化方法
*/
private static void deSerializeMethod() {
try {
ObjectInputStream inputStream = new ObjectInputStream(new FileInputStream(new File("Person")));
Person person = (Person)inputStream.readObject();
System.out.println("反序列化成功 : "+person);
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
运行main方法结果为 :
序列化成功
反序列化成功 : Person [name=wang, id=1]
- 静态变量的序列化
序列化不保存静态变量的状态.
import java.io.Serializable;
public class Person implements Serializable {
private static final long serialVersionUID = 1L;
//静态变量
public static int age = 20;
private String name;
private int id;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
@Override
public String toString() {
return "Person [name=" + name + ", id=" + id + "]";
}
}
序列化方法还是用上面的代码,反序列化将静态变量的值作修改:
/**
* 反序列化方法
*/
private static void deSerializeMethod() {
try {
//这里重新设置静态变量的值
Person.age = 10;
ObjectInputStream inputStream = new ObjectInputStream(new FileInputStream(new File("Person")));
Person person = (Person)inputStream.readObject();
System.out.println("反序列化成功 : "+person);
System.out.println(person.age);
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
再次运行main方法,结果为:
序列化成功
反序列化成功 : Person [name=wang, id=1]
10 //发现这里的值是修改后的值
-
transient关键字
transient关键字修饰的变量不被序列化,还是刚才的
Person
类,我们在name
属性上加上这个属性看看结果:import java.io.Serializable; public class Person implements Serializable { private static final long serialVersionUID = 1L; //静态变量 public static int age = 20; //注意这里加了 transient 关键字 private transient String name; private int id; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getId() { return id; } public void setId(int id) { this.id = id; } @Override public String toString() { return "Person [name=" + name + ", id=" + id + "]"; } }
还是刚才的main方法再次执行结果为:
序列化成功 反序列化成功 : Person [name=null, id=1] //这里name没有值了,表明没有被序列化,所以反序列化时没有值 10
-
父子类序列化问题
父类如果要序列化也要实现
Serializable
接口.看下面的示例:
//Human没有序列化 public class Human { public int height; public int getHeight() { return height; } public void setHeight(int height) { this.height = height; } }
public class Person extends Human implements Serializable,Cloneable { private static final long serialVersionUID = 1L; public static int age = 20; private String name; private int id; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getId() { return id; } public void setId(int id) { this.id = id; } @Override public String toString() { return "Person [name=" + name + ", id=" + id + ", height=" + height + "]"; } }
import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; public class SerilizedDemo { public static void main(String[] args) { serializeMethod(); deSerializeMethod(); } /** * 序列化方法 */ private static void serializeMethod() { try { ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(new File("Person"))); Person person = new Person(); person.setId(1); person.setName("wang"); //这里设置了值 person.setHeight(170); out.writeObject(person); out.flush(); out.close(); System.out.println("序列化成功"); } catch (IOException e) { e.printStackTrace(); } } /** * 反序列化方法 */ private static void deSerializeMethod() { try { ObjectInputStream inputStream = new ObjectInputStream(new FileInputStream(new File("Person"))); Person person = (Person)inputStream.readObject(); System.out.println("反序列化成功 : "+person); } catch (IOException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } } }
运行main方法,结果为 :
序列化成功 反序列化成功 : Person [name=wang, id=1, height=0]//这里height为0,不是我们设置的值,说明没有序列化
现在我们将
Human
类实现序列化:import java.io.Serializable; //实现序列化 public class Human implements Serializable{ private static final long serialVersionUID = -1149910849791261774L; public int height; public int getHeight() { return height; } public void setHeight(int height) { this.height = height; } }
再次运行main方法结果为:
序列化成功 反序列化成功 : Person [name=wang, id=1, height=170]//发现设置的值生效了
-
序列化实现深克隆
浅拷贝 : 不复制引用
深拷贝 : 复制引用
public class Test {
public static void main(String[] args) {
deepCloneTest();
}
private static void deepCloneTest() {
Person person = new Person();
Teacher teacher = new Teacher();
teacher.setName("wang");
person.setId(1);
person.setName("peng");
person.setTeacher(teacher);
try {
//浅拷贝
Person person1 = (Person) person.clone();
//当这里修改值时会把 person1 里面的teacher的值也修改,所以下面的结果为
// person : Person [name=peng, id=1, teacher=Teacher [name=ming]]
//person1 : Person [name=peng, id=1, teacher=Teacher [name=ming]]
//person2 : Person [name=peng, id=1, teacher=Teacher [name=ming]]
// teacher.setName("ming");
//深拷贝
Person person2 = person.deepClone();
//这里只会改前面的结果不会改变person2里面teacher的值
//person : Person [name=peng, id=1, teacher=Teacher [name=ming]]
//person1 : Person [name=peng, id=1, teacher=Teacher [name=ming]]
//person2 : Person [name=peng, id=1, teacher=Teacher [name=wang]]
teacher.setName("ming");
System.out.println("person : "+person.toString());
System.out.println("person1 : "+person1.toString());
System.out.println("person2 : "+person2.toString());
} catch (ClassNotFoundException | IOException | CloneNotSupportedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public class Person implements Serializable,Cloneable {
private static final long serialVersionUID = 1L;
public static int age = 20;
private String name;
private int id;
private Teacher teacher;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public Teacher getTeacher() {
return teacher;
}
public void setTeacher(Teacher teacher) {
this.teacher = teacher;
}
/**
* 深克隆方法
* @return
* @throws ClassNotFoundException
* @throws IOException
*/
public Person deepClone() throws ClassNotFoundException, IOException {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream os = new ObjectOutputStream(bos);
os.writeObject(this);
ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
ObjectInputStream is = new ObjectInputStream(bis);
Person student = (Person)is.readObject();
return student;
}
/**
* 浅拷贝
*/
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
@Override
public String toString() {
return "Person [name=" + name + ", id=" + id + ", teacher=" + teacher.toString() + "]";
}
}
public class Teacher implements Serializable,Cloneable {
private static final long serialVersionUID = -3273424656529143724L;
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Teacher [name=" + name + "]";
}
}
java序列化得缺点 :
- 无法跨语言
- 序列化之后的码流太大
- 序列化性能低
网友评论