序列化 (Serialization)这是一个将对象的状态信息转换为可存储或传输的过程。在序列化期间,对象将其当前状态写入临时或持久的存储区域。在未来,通过从存储区域读取或反序列化对象的状态,可以重新创建对象。同样,反序列化是将字节序列恢复为Java对象的过程。通俗易懂,就像好莱坞大片中的瞬移,把一个人或物体变成一串数字和字母流,然后传输到很远的地方,然后把这串数字和字母流回原来的物体。这个过程和java的序列化反序列化类似地,将物体变成数字母流是序列化,将数字母流变成物体是反序列化。通常,对象实例的所有字段都会被序列化,这意味着数据将被表示为实例的序列化数据。这样,在不依赖成员可访问性的情况下,可以解释该格式的代码可以确定数据的值。类似地,反序列化从序列化的表示形式中提取数据,并直接设置对象状态,这与可访问性规则无关。
对于任何可能包含重要安全数据的对象,如果可能的话,对象都不应该序列化。如果必须是可序列化的,请尝试生成特定的字段来保存不可序列化的重要数据。如果无法实现这一点,请注意,该数据将向任何具有序列化权限的代码公开,并确保不允许任何恶意代码获得该权限。
简单来说就像看大科幻电影。 里面有很多这样的情节。 将一个人或物体变成一串数字和字母流 然后传输到很远的地方,然后将这串数字和字母流回原始物体 这个过程与序列化反序列化非常相似 将物体变成数字母流是序列化的 将数字字母流成物体是反序列
在实现在Java对象的序列化和反序列化过程中,我们需要注意以下几点:
1.如果对象需要序列化,Serializable接口需要实现
2.ObjectOutputStream 用于序列化
3.ObjectInputStream 用于反序列化
4.transient修改的变量不能序列化
5.static 修改后的变量不能序列化
实现实现java对象的序列化和反序列化代码如下:
import java.io.*;
////serializable接口可以实现对象的序列化
class Person implements Serializable {
public String name;
public int age;
public String sex;
///transient修改的变量不能序列化
transient public String cardId;
//static 修改后的变量不能序列化
public static String phoneNum;
public Person(String name, int age, String sex, String cardId) {
this.name = name;
this.age = age;
this.sex = sex;
this.cardId = cardId;
}
public static void setPhoneNum(String phoneNum) {
Person.phoneNum = phoneNum;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
", sex='" + sex + '\'' +
", cardId='" + cardId + '\'' +
", phoneNum='" + phoneNum + '\'' +
'}';
}
}
public class SerializTest {
public static void main(String[] args) {
Person.person = new Person("Listen", 21, "MAN", "100100100111");
Person.setPhoneNum("120");
//序列化一个对象
serializPreson(person);
///反序列化对象
Person personRet = desSerializable();
System.out.println(personRet);
}
private static Person desSerializable() {
Person person = null;
try (ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream("D:\\java\\java.txt"))){
person = (Person) objectInputStream.readObject();
System.out.println("反序列化成功");
} catch (IOException | ClassNotFoundException e) {
e.getStackTrace();
}
return person;
}
private static void serializPreson(Person person) {
try (ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("D:\\java\\java.txt"))){
///将person对象序列输入文件
// 这个 writeObject 集序列化+写文件 两者同时完成
objectOutputStream.writeObject(person);
System.out.println("序列化成功");
} catch (IOException e) {
e.getStackTrace();
}
}
}
我们可以从上面的结果中看到cardid被transient修改,无法序列化,因此得到的反序列化结果是null 。然而,我们说,由static修改的phonenum不能序列化,但它不显示null。这是因为它是一个静态变量,在代码编译过程中已经存储在方法区域,因此他可以获得值,而无需序列化。
如果一个类想要序列化,就需要实现一个类Serialzable接口。类中静态变量的值不会序列化,transient修改的属性不会序列化,内置类型为对应的0值。引用类型为null。实现这个Serializable接口时,一定要给这个SerialversionUID赋值,最好设置为1L,不同SerialversionUID的值会影响反序列化。掌握java序列化和反序列化可以更好地提高系统的性能,使程序更具维护性。