Java 的序列化 (Serializable)(Day_09)
我们的火,要把世界都点燃
-
运行环境
JDK8 + IntelliJ IDEA 2018.3
-
什么是序列化,反序列化
序列化是将对象状态转换为可保持或传输的格式的过程。
与序列化相对的是反序列化,它将流转换为对象。这两个过程结合起来,可以轻松地存储和传输数据。
反序列化是指将存储在存储媒体中的对象状态装换成对象的过程
-
序列化的作用
- 以某种存储形式使自定义对象持久化;
- 将对象从一个地方传递到另一个地方。
- 保证对象的完整性和可传递性。
- 使程序更具维护性
-
如何实现类的序列化?
实现Serializable接口
-
编程实现类的序列化:
1 关键代码 2 public static void main(String[] args) throws Exception{ 3 4 Student stu = new Student(); 5 6 File file = new File("bb.dat"); 7 8 ObjectOutputStream oos = new ObjectOutputStream(new 9 10 FileOutputStream(file)); 11 12 oos.writeObject(stu); 13 }
-
编程实现类的反序列化:
1 public static void main(String[] args) throws Exception{ 2 3 File file = new File("bb.dat"); 4 5 ObjectInputStream ois = new ObjectInputStream(new 6 7 FileInputStream(file)); 8 9 Object obj = ois.readObject(); 10 11 System.out.println(obj.hashCode()); 12 }
-
多对象Serializable(序列化)的实现
序列化鱼,还需要序列化鱼的生存环境---水。
1 //环境: 水 2 import java.io.Serializable; 3 4 public class Water implements Serializable { 5 int opacity; 6 7 public Water(int opacity) { 8 this.opacity = opacity; 9 } 10 11 public Water() { 12 } 13 14 @Override 15 public String toString() { 16 return "Water{" + 17 "opacity=" + opacity + 18 '}'; 19 } 20 }
1 import java.io.Serializable; 2 3 public class Fish implements Serializable { 4 5 String color; 6 String type; 7 Water enviroment; 8 9 public Fish(String color, String type, Water enviroment) { 10 this.color = color; 11 this.type = type; 12 this.enviroment = enviroment; 13 } 14 15 public Fish(String color, String type) { 16 this.color = color; 17 this.type = type; 18 } 19 20 public Fish() { 21 } 22 23 @Override 24 public String toString() { 25 return "Fish{" + 26 "color='" + color + '\'' + 27 ", type='" + type + '\'' + 28 ", enviroment=" + enviroment + 29 '}'; 30 } 31 }
import java.io.*; // 序列化 public class TestFish { public static void main(String[] args) { Water enro = new Water(99); Fish fish = new Fish("金色", "鲤鱼", enro); File file = new File("fish.bat"); try { ObjectOutputStream oos = new ObjectOutputStream( new FileOutputStream(file)); oos.writeObject(fish); oos.close(); } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } } // 反序列化 import java.io.FileInputStream; import java.io.IOException; import java.io.ObjectInputStream; public class TestFish2 { public static void main(String[] args) { try { ObjectInputStream objectInputStream=new ObjectInputStream(new FileInputStream("fish.bat")); try { Fish fish=(Fish) objectInputStream.readObject(); System.out.println(fish); objectInputStream.close(); } catch (ClassNotFoundException e) { e.printStackTrace(); } } catch (IOException e) { e.printStackTrace(); } } }
¤ transient关键字:将不需要序列化的属性前添加关键字transient,序列化对象的时候,这个属性就不会被序列化。
- 浅克隆 —— 只克隆本身
被复制对象的所有变量都含有与原来对象相同的值,而所有的对其他对象的引用仍然只指向原来的对象。
代码演示:
1 package com.wenhaitao.yxdemo.demo4; 2 public class Professor { 3 String name; 4 int age; 5 6 public Professor(String name, int age) { 7 super(); 8 this.name = name; 9 this.age = age; 10 } 11 12 public Professor() { 13 super(); 14 } 15 16 @Override 17 public String toString() { 18 return "Professor [age=" + age + ", name=" + name + "]"; 19 } 20 21 }
1 // 浅克隆 2 3 public class Student implements Cloneable { 4 String name; 5 int age; 6 7 Professor p; 8 9 public Professor getP() { 10 return p; 11 } 12 13 public void setP(Professor p) { 14 this.p = p; 15 } 16 17 @Override 18 public Object clone() throws CloneNotSupportedException { 19 return super.clone(); 20 } 21 22 public Student() { 23 super(); 24 } 25 26 public Student(String name, int age) { 27 super(); 28 this.name = name; 29 this.age = age; 30 } 31 32 public Student(String name, int age, Professor p) { 33 super(); 34 this.name = name; 35 this.age = age; 36 this.p = p; 37 } 38 39 @Override 40 public String toString() { 41 return "Student [age=" + age + ", name=" + name + ", p=" + p + "]"; 42 } 43 44 public static void main(String[] args) throws CloneNotSupportedException { 45 Professor p = new Professor("feifeiye",50); 46 Student s1 = new Student("zhangsan", 19, p); 47 Student s2 = (Student) s1.clone(); 48 System.out.println(s1); 49 System.out.println(s2); 50 System.out.println(s1==s2); 51 52 s2.p.name = "wangwu"; 53 s2.p.age = 90; 54 System.out.println(s2); 55 System.out.println(s1); 56 } 57 }
- 深克隆 —— 克隆本身和所有的成员
概述:
被复制对象的所有变量都含有与原来的对象相同的值,除去那些引用其他对象的变量,
那些引用其他对象的变量将指向被复制过的新对象,而不再指向原有的那些被引用的对象,
换言之,深复制把要复制的对象所引用的对象都复制了一遍。
代码演示:
1 2 public class Professor implements Cloneable{ 3 String name; 4 int age; 5 6 public Professor(String name, int age) { 7 super(); 8 this.name = name; 9 this.age = age; 10 } 11 12 public Professor() { 13 super(); 14 } 15 16 public Object clone() throws CloneNotSupportedException { 17 return super.clone(); 18 } 19 20 21 @Override 22 public String toString() { 23 return "Professor [age=" + age + ", name=" + name + "]"; 24 } 25 26 }
1 //深克隆 2 public class Student implements Cloneable { 3 String name; 4 int age; 5 6 Professor p; 7 8 public Professor getP() { 9 return p; 10 } 11 12 public void setP(Professor p) { 13 this.p = p; 14 } 15 16 @Override 17 public Object clone() throws CloneNotSupportedException { 18 Object obj = super.clone(); 19 Student s = (Student) obj; 20 s.p = (Professor) this.p.clone(); 21 return obj; 22 } 23 24 public Student() { 25 super(); 26 } 27 28 public Student(String name, int age) { 29 super(); 30 this.name = name; 31 this.age = age; 32 } 33 34 public Student(String name, int age, Professor p) { 35 super(); 36 this.name = name; 37 this.age = age; 38 this.p = p; 39 } 40 41 @Override 42 public String toString() { 43 return "Student [age=" + age + ", name=" + name + ", p=" + p + "]"; 44 } 45 46 public static void main(String[] args) throws CloneNotSupportedException { 47 Professor p = new Professor("肥肥也",19); 48 Student s1 = new Student("都一样", 19, p); 49 Student s2 = (Student) s1.clone(); 50 System.out.println(s1);// 51 System.out.println(s2); 52 System.out.println(s1==s2); 53 54 s2.p.name = "zhaoliu"; 55 s2.p.age = 60; 56 System.out.println(s2);// 57 System.out.println(s1); 58 } 59 }
总结:
- 如果自定义类型包含引用类型的数据成员,必须考虑Clone方法是实现浅拷贝(shallow copy)还是深拷贝(deep copy)。
- 浅拷贝是指副本对象中的引用类型的数据成员与源对象的数据成员指向相同的对象。而如果是深拷贝,则必须创建整个对象的结构,副本对象中的引用 类型的数据成员与源对象的数据成员指向不同的对象。
- 当一个父类实现序列化,子类自动实现序列化,不需要显式实现Serializable接口;
- 当一个对象的实例变量引用其他对象,序列化该对象时也把引用对象进行序列化;
PS:
如果,您希望更容易地发现我的新博客,不妨点击一下关注。
如果你觉得本篇文章对你有所帮助,请给予我更多的鼓励,
因为,我的写作热情也离不开您的肯定支持,感谢您的阅读,我是【肥肥也】!