序列化
为什么:程序运行的过程中,所有变量都是在内存中操作的,当程序一旦执行完毕,结束退出后,变量占有的内存就被操作系统回收了。 因此我们需要将某些数据持久化存储到磁盘中,下次运行的时候从磁盘中读取相关数据。
是什么:我们将变量从内存中变成可以存储或传输的过程称之为序列化。
怎么用:对象的序列化主要有两种用途:(持久化+网络通信+RMI)
1) 一是可以实现数据的持久化,把对象的字节序列永久地保存到硬盘上。
2) 二是可以对象数据的远程通信,在网络上传送对象的字节序列。(比如转为Json数组)
3)三是远程方法调用时(RMI,一种用于实现远程过程调用(RPC)的Java API)
代码实例:
package pac.IOstream;
import java.io.*;
/*
ObjectOutputStream:对象的序列化流
作用:把对象以流的方式写入到文件中保存
使用步骤:
1.创建ObjectOutputStream对象,构造方法中传递字节输出流
2.使用ObjectOutputStream对象中的方法writeObject,把对象写入到文件中
3.释放资源
ObjectInputStream:对象的反序列化流
作用:把文件中保存的对象,以流的方式读取出来使用
使用步骤:
1.创建ObjectInputStream对象,构造方法中传递字节输入流
2.使用ObjectInputStream对象中的方法readObject读取保存对象的文件
3.释放资源
4.使用读取出来的对象(打印)
readObject方法声明抛出了ClassNotFoundException(class文件找不到异常)
当不存在对象的class文件时抛出此异常
反序列化的前提:
1.类必须实现Serializable
2.必须存在类对应的class文件
另外,当JVM反序列化对象时,能找到class文件,但是class文件在序列化对象之后发生了修改,
那么反序列化操作也会失败,抛出一个`InvalidClassException`异常。
Serializable` 接口给需要序列化的类,提供了一个序列版本号。`
serialVersionUID` 该版本号的目的在于验证序列化的对象和对应类是否版本匹配。
*/
public class IOStream {
public static void main(String[] args) {
Employee employee = new Employee();
employee.name = "王伟光";
employee.address = "安阳市";
employee.age = 24;
employee.addressCheck();
Employee employee1 = null;
try {
// 序列化
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("a.txt"));
out.writeObject(employee);
out.close();
System.out.println("Serialized data is saved");
// 反序列化
ObjectInputStream in = new ObjectInputStream(new FileInputStream("a.txt"));
employee1 = (Employee) in.readObject();
in.close();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
System.out.println("Employee class not found");
e.printStackTrace();
}
// 无异常,直接打印输出
System.out.println("Name: " + employee1.name); // zhangsan
System.out.println("Address: " + employee1.address); // beiqinglu
System.out.println("age: " + employee1.age); // 0
}
}
/*
Serializable接口也叫标记型接口
要进行序列化和反序列化的类必须实现Serializable接口,就会给类添加一个标记
没有:就会抛出 NotSerializableException异常
static关键字:静态关键字
静态优先于非静态加载到内存中(静态优先于对象进入到内存中)
被static修饰的成员变量不能被序列化的,序列化的都是对象
transient关键字:瞬态关键字
被transient修饰成员变量,不能被序列化
*/
class Employee implements java.io.Serializable {
// 加入序列版本号
private static final long serialVersionUID = 1L;
public String name;
public String address;
public transient int age; // transient瞬态修饰成员,不会被序列化
public void addressCheck() {
System.out.println("Address check : " + name + " -- " + address + "--" + age);
}
}
不足:
1 无法跨语言
2 序列化后的码流太大
3 序列化性能太低
解决:无论是序列化后的码流大小,还是序列化的性能,JDK 默认的序列化机制表现都很差。因此,我们通常不会选择 Java 序列化作为远程跨节点调用的编解码框架。而是使用业界提供的很多优秀的编解码框架,它们在克服了 JDK 默认的序列化框架缺点的基础上,还增加了很多亮点。例如:Google 的 Protobuf、Facebook 的 Thrift 和 JBoss 的 Marshalling 等等
详细:https://blog.csdn.net/zhengzhaoyang122/article/details/100780222
拷贝
为什么:想对一个对象进行处理,又想保留原有的数据进行接下来的操作,就需要克隆了,Java语言中克隆针对的是类的实例。
是什么:
-
浅拷贝只是复制了对象的引用地址,两个对象指向同一个内存地址,所以修改其中任意的值,另一个值都会随之变化,这就是浅拷贝(Object1=Object2)
-
深拷贝是将对象及值复制过来,两个对象修改其中任意的值另一个值不会改变,这就是深拷贝(例:重写Object.clone(),通过序列化和反序列化)
怎么用:
深拷贝的两种方式:
1). 实现Cloneable接口并重写Object类中的clone()方法;
2). 实现Serializable接口,通过对象的序列化和反序列化实现克隆,可以实现真正的深度克隆。
比较:基于序列化和反序列化实现的克隆不仅仅是深度克隆,更重要的是通过泛型限定,可以检查出要克隆的对象是否支持序列化,这项检查是编译器完成的,不是在运行时抛出异常,这种是方案明显优于使用Object类的clone方法克隆对象。让问题在编译的时候暴露出来总是好过把问题留到运行时。
代码实例:
package wangc.pac.clone;
public class ObjectClone {
public static void main(String[] args) throws CloneNotSupportedException {
//浅拷贝:值传递
Person person1 = new Person("王c", 23);
Person person1clone = person1;
System.out.println(person1clone);
System.out.println("person1==person1clone:" + (person1==person1clone));
//深拷贝:clone方法
// ① 实现Cloneable接口,这是一个标记接口
//② 覆盖clone()方法,可见性提升为public
Person person2 = new Person("李b", 18);
Person person2clone = (Person) person2.clone();
System.out.println(person2clone);
System.out.println("person2==person2clone:" + (person2==person2clone));
}
}
class Person implements Cloneable{
String name;
int age;
public Person() {
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
序列化实现。。。