Java序列化

2021-02-06 09:15

阅读:311

标签:common   变量   读取   添加   持久   父类   级别   tran   txt   

Java序列化

Java序列化将对象转化成二进制字节数组,可以将二进制数据保存到磁盘或者进行网络传输,实现了对对象状态保存,并且可通过反序列化来获取完全相同的对象副本,达到对象持久化的目的。

序列化的要求:

1. 序列化对象必须实现java.io.Serializable接口。

2. 序列化类中需添加serialVersionUID。如:private static final long serialVersionUID = 1L;

3. 若序列化对象中的成员变量是对象,则其也要实现java.io.Serializable接口。

 

注意点:

1. 类的对象序列化后,类中的serialVersionUID不可修改(修改会导致反序列化会失败)。

2. 类的对象序列化后,类中的变量有增删不会影响序列化,只是值会丢失。

3. 若父类序列化了,子类会继承父类的序列化,子类无需再显式实现java.io.Serializable接口。

4. 若父类没有序列化,子类序列化了,子类中的成员变量能正常序列化,但父类的中的成员变量不能序列化,会丢失。

5. 若成员变量不需序列化(敏感类成员变量,如密码之类的),加上transient关键字修饰,不参与序列化过程(transient一般只用于这种场景)。

6. 静态变量属于类级别的,不属于对象,属于类,不能被序列化。

7.常见的Date、String类已经实现了序列化,因此可以直接持久化。

 

另一种序列化方式是实现Exteranlizable接口。需要重写writeExternalreadExternal方法(这两个方法中若添加了transient字段的读取、写入,那么transient就失效了),它的效率比Serializable高一些,并且可以决定哪些成员变量需要序列化,但是对大量对象,或者重复对象,则效率低。

 

打开看Serializable接口源码,发现只是个空接口:

package java.io;

public interface Serializable {

}

 

关于serialVersionUID

  它在反序列化期间用于验证序列化对象的发送方和接收方是否已为该对象加载了与序列化兼容的类JVM会把传来的字节流中的serialVersionUID与本地相应实体(类)的serialVersionUID进行比较,如果相同就认为是一致的,可以进行反序列化;否则反序列化将导致InvalidClassException异常。如果可序列化类没有显式声明serialVersionUID,则序列化运行时将根据该类计算该类的默认serialVersionUID值。

实例:

 1 public class User implements Serializable{
 2 
 3     private static final long serialVersionUID = 1L;
 4 
 5     private String name;
 6 
 7     private transient String pwd;
 8 
 9     //setter/getter省略
10 
11 }

 

 1 // 存储对象到文件
 2 
 3 User user = new User("jzx","123");
 4 
 5 FileOutputStream fos = null;
 6 
 7 ObjectOutputStream oos = null;
 8 
 9 try{
10 
11    fos = new FileOutputStream("C:/Users/JZX/Desktop/demo.txt");
12 
13    oos = new ObjectOutputStream(fos);
14 
15    oos.writeObject(user);
16 
17  } catch (IOException e) {
18 
19      e.printStackTrace();
20 
21  } finally {
22 
23    if(fos != null){
24 
25        fos.close();
26 
27    }
28 
29     if(oos != null){
30 
31        oos.flush();
32 
33        oos.close();
34 
35     }
36 
37  }

 

 1 // 读取序列化存储的对象
 2 
 3 FileInputStream fis = null;
 4 
 5 ObjectInputStream ois = null;
 6 
 7 try{
 8 
 9     fis = new FileInputStream("C:/Users/JZX/Desktop/demo.txt");
10 
11     ois = new ObjectInputStream(fis);
12 
13     System.out.println(ois.readObject());
14 
15 } catch (IOException e) {
16 
17      e.printStackTrace();
18 
19 } finally {
20 
21   if(fis != null){
22 
23       fis.close();
24 
25   }
26 
27   if(ois != null){
28 
29       ois.close();
30 
31   }
32 
33 }

输出:

User{name=‘jzx‘, pwd=‘null‘}

可见加了transient pwd并没有被序列化存储。

 

也可借助org.apache.commons.lang3.SerializationUtils实现对象的序列化及反序列化

1 byte[] bytes = SerializationUtils.serialize (user);
2 
3 User user = SerializationUtils.deserialize (bytes);
4 
5 System.out.println(user);

 

Java序列化

标签:common   变量   读取   添加   持久   父类   级别   tran   txt   

原文地址:https://www.cnblogs.com/jiazhongxin/p/12781876.html


评论


亲,登录后才可以留言!