国产片侵犯亲女视频播放_亚洲精品二区_在线免费国产视频_欧美精品一区二区三区在线_少妇久久久_在线观看av不卡

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - Java教程 - Java序列化和反序列化_動力節點Java學院整理

Java序列化和反序列化_動力節點Java學院整理

2020-09-29 13:57動力節點 Java教程

把對象轉換為字節序列的過程稱為對象的序列化,把字節序列恢復為對象的過程稱為對象的反序列化。接下來通過本文給大家介紹Java序列化和反序列化及主要的兩種用途,感興趣的的友參考下吧

一、序列化和反序列化的概念

  把對象轉換為字節序列的過程稱為對象的序列化。

  把字節序列恢復為對象的過程稱為對象的反序列化。

  對象的序列化主要有兩種用途:

  1) 把對象的字節序列永久地保存到硬盤上,通常存放在一個文件中;

  2) 在網絡上傳送對象的字節序列。

  在很多應用中,需要對某些對象進行序列化,讓它們離開內存空間,入住物理硬盤,以便長期保存。比如最常見的是Web服務器中的Session對象,當有 10萬用戶并發訪問,就有可能出現10萬個Session對象,內存可能吃不消,于是Web容器就會把一些seesion先序列化到硬盤中,等要用了,再把保存在硬盤中的對象還原到內存中。

  當兩個進程在進行遠程通信時,彼此可以發送各種類型的數據。無論是何種類型的數據,都會以二進制序列的形式在網絡上傳送。發送方需要把這個Java對象轉換為字節序列,才能在網絡上傳送;接收方則需要把字節序列再恢復為Java對象。

二、JDK類庫中的序列化API

  java.io.ObjectOutputStream代表對象輸出流,它的writeObject(Object obj)方法可對參數指定的obj對象進行序列化,把得到的字節序列寫到一個目標輸出流中。

  java.io.ObjectInputStream代表對象輸入流,它的readObject()方法從一個源輸入流中讀取字節序列,再把它們反序列化為一個對象,并將其返回。

  只有實現了Serializable和Externalizable接口的類的對象才能被序列化。Externalizable接口繼承自 Serializable接口,實現Externalizable接口的類完全由自身來控制序列化的行為,而僅實現Serializable接口的類可以 采用默認的序列化方式 。

  對象序列化包括如下步驟:

  1) 創建一個對象輸出流,它可以包裝一個其他類型的目標輸出流,如文件輸出流;

  2) 通過對象輸出流的writeObject()方法寫對象。

  對象反序列化的步驟如下:

  1) 創建一個對象輸入流,它可以包裝一個其他類型的源輸入流,如文件輸入流;

  2) 通過對象輸入流的readObject()方法讀取對象。

對象序列化和反序列范例:

  定義一個Person類,實現Serializable接口 

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
import java.io.Serializable;
/**
* <p>ClassName: Person<p>
* <p>Description:測試對象序列化和反序列化<p>
*
* @version 1.0 V
*
*/
public class Person implements Serializable {
/**
* 序列化ID
*/
private static final long serialVersionUID = -5809782578272943999L;
private int age;
private String name;
private String sex;
public int getAge() {
 return age;
}
public String getName() {
 return name;
}
public String getSex() {
 return sex;
}
public void setAge(int age) {
 this.age = age;
}
public void setName(String name) {
 this.name = name;
}
public void setSex(String sex) {
 this.sex = sex;
}
}

  序列化和反序列化Person類對象 

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.text.MessageFormat;
/**
* <p>ClassName: TestObjSerializeAndDeserialize<p>
* <p>Description: 測試對象的序列化和反序列<p>
*
* @version 1.0 V
*
*/
public class TestObjSerializeAndDeserialize {
public static void main(String[] args) throws Exception {
 SerializePerson();//序列化Person對象
 Person p = DeserializePerson();//反序列Perons對象
 System.out.println(MessageFormat.format("name={0},age={1},sex={2}",
      p.getName(), p.getAge(), p.getSex()));
}
/**
* MethodName: SerializePerson
* Description: 序列化Person對象
* @author xudp
* @throws FileNotFoundException
* @throws IOException
*/
private static void SerializePerson() throws FileNotFoundException,
 IOException {
 Person person = new Person();
 person.setName("gacl");
person.setAge(25);
 person.setSex("男");
 // ObjectOutputStream 對象輸出流,將Person對象存儲到E盤的Person.txt文件中,完成對Person對象的序列化操作
 ObjectOutputStream oo = new ObjectOutputStream(new FileOutputStream(
  new File("E:/Person.txt")));
 oo.writeObject(person);
 System.out.println("Person對象序列化成功!");
 oo.close();
}
/**
* MethodName: DeserializePerson
* Description: 反序列Perons對象
*
* @return
* @throws Exception
* @throws IOException
*/
private static Person DeserializePerson() throws Exception, IOException {
 ObjectInputStream ois = new ObjectInputStream(new FileInputStream(
  new File("E:/Person.txt")));
 Person person = (Person) ois.readObject();
 System.out.println("Person對象反序列化成功!");
 return person;
}
}

代碼運行結果如下:

Java序列化和反序列化_動力節點Java學院整理

序列化Person成功后在E盤生成了一個Person.txt文件,而反序列化Person是讀取E盤的Person.txt后生成了一個Person對象

 三、serialVersionUID的作用

  serialVersionUID: 字面意思上是序列化的版本號,凡是實現Serializable接口的類都有一個表示序列化版本標識符的靜態變量

?
1
private static final long serialVersionUID

  實現Serializable接口的類如果類中沒有添加serialVersionUID,那么就會出現如下的警告提示

Java序列化和反序列化_動力節點Java學院整理  

  用鼠標點擊就會彈出生成serialVersionUID的對話框,如下圖所示:  

Java序列化和反序列化_動力節點Java學院整理

  serialVersionUID有兩種生成方式:

  采用這種方式生成的serialVersionUID是1L,例如:

?
1
private static final long serialVersionUID = 1L;

  采用這種方式生成的serialVersionUID是根據類名,接口名,方法和屬性等來生成的,例如:

?
1
private static final long serialVersionUID = 4603642343377807741L;

  添加了之后就不會出現那個警告提示了,如下所示:  

  扯了那么多,那么serialVersionUID(序列化版本號)到底有什么用呢,我們用如下的例子來說明一下serialVersionUID的作用,看下面的代碼: 

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
public class TestSerialversionUID {
public static void main(String[] args) throws Exception {
 SerializeCustomer();// 序列化Customer對象
 Customer customer = DeserializeCustomer();// 反序列Customer對象
 System.out.println(customer);
}
/**
* MethodName: SerializeCustomer
* Description: 序列化Customer對象
*
* @throws FileNotFoundException
* @throws IOException
*/
private static void SerializeCustomer() throws FileNotFoundException,
 IOException {
 Customer customer = new Customer("gacl",);
 // ObjectOutputStream 對象輸出流
 ObjectOutputStream oo = new ObjectOutputStream(new FileOutputStream(
  new File("E:/Customer.txt")));
 oo.writeObject(customer);
 System.out.println("Customer對象序列化成功!");
 oo.close();
}
/**
* MethodName: DeserializeCustomer
* Description: 反序列Customer對象
*
* @return
* @throws Exception
* @throws IOException
*/
private static Customer DeserializeCustomer() throws Exception, IOException {
 ObjectInputStream ois = new ObjectInputStream(new FileInputStream(
  new File("E:/Customer.txt")));
 Customer customer = (Customer) ois.readObject();
 System.out.println("Customer對象反序列化成功!");
 return customer;
}
}
/**
* <p>ClassName: Customer<p>
* <p>Description: Customer實現了Serializable接口,可以被序列化<p>
*
* @version . V
*
*/
class Customer implements Serializable {
//Customer類中沒有定義serialVersionUID
private String name;
private int age;
public Customer(String name, int age) {
 this.name = name;
 this.age = age;
}
/*
* @MethodName toString
* @Description 重寫Object類的toString()方法
* @author xudp
* @return string
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
 return "name=" + name + ", age=" + age;
}
}

運行結果:

Java序列化和反序列化_動力節點Java學院整理

序列化和反序列化都成功了。

下面我們修改一下Customer類,添加多一個sex屬性,如下: 

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
class Customer implements Serializable {
//Customer類中沒有定義serialVersionUID
private String name;
private int age;
//新添加的sex屬性
private String sex;
public Customer(String name, int age) {
 this.name = name;
 this.age = age;
}
public Customer(String name, int age,String sex) {
 this.name = name;
 this.age = age;
 this.sex = sex;
}
/*
* @MethodName toString
* @Description 重寫Object類的toString()方法
*
* @return string
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
 return "name=" + name + ", age=" + age;
}
}

  然后執行反序列操作,此時就會拋出如下的異常信息:

?
1
2
3
4
Exception in thread "main" java.io.InvalidClassException: Customer;
local class incompatible:
stream classdesc serialVersionUID = -88175599799432325,
local class serialVersionUID = -5182532647273106745

  意思就是說,文件流中的class和classpath中的class,也就是修改過后的class,不兼容了,處于安全機制考慮,程序拋出了錯誤,并且拒絕載入。那么如果我們真的有需求要在序列化后添加一個字段或者方法呢?應該怎么辦?那就是自己去指定serialVersionUID。在TestSerialversionUID例子中,沒有指定Customer類的serialVersionUID的,那么java編譯器會自動給這個class進行一個摘要算法,類似于指紋算法,只要這個文件 多一個空格,得到的UID就會截然不同的,可以保證在這么多類中,這個編號是唯一的。所以,添加了一個字段后,由于沒有顯指定 serialVersionUID,編譯器又為我們生成了一個UID,當然和前面保存在文件中的那個不會一樣了,于是就出現了2個序列化版本號不一致的錯誤。因此,只要我們自己指定了serialVersionUID,就可以在序列化后,去添加一個字段,或者方法,而不會影響到后期的還原,還原后的對象照樣可以使用,而且還多了方法或者屬性可以用。

  下面繼續修改Customer類,給Customer指定一個serialVersionUID,修改后的代碼如下: 

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
class Customer implements Serializable {
 /**
 * Customer類中定義的serialVersionUID(序列化版本號)
 */
 private static final long serialVersionUID = -L;
 private String name;
 private int age;
 //新添加的sex屬性
 //private String sex;
 public Customer(String name, int age) {
  this.name = name;
  this.age = age;
 }
 /*public Customer(String name, int age,String sex) {
  this.name = name;
  this.age = age;
  this.sex = sex;
 }*/
 /*
 * @MethodName toString
 * @Description 重寫Object類的toString()方法
 * @author xudp
 * @return string
 * @see java.lang.Object#toString()
 */
 @Override
 public String toString() {
  return "name=" + name + ", age=" + age;
 }
}

  重新執行序列化操作,將Customer對象序列化到本地硬盤的Customer.txt文件存儲,然后修改Customer類,添加sex屬性,修改后的Customer類代碼如下: 

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
class Customer implements Serializable {
  /**
  * Customer類中定義的serialVersionUID(序列化版本號)
  */
  private static final long serialVersionUID = -5182532647273106745L;
  private String name;
  private int age;
  //新添加的sex屬性
  private String sex;
  public Customer(String name, int age) {
   this.name = name;
   this.age = age;
  }
  public Customer(String name, int age,String sex) {
   this.name = name;
   this.age = age;
   this.sex = sex;
  }
  /*
  * @MethodName toString
  * @Description 重寫Object類的toString()方法
  *
  * @return string
  * @see java.lang.Object#toString()
  */
  @Override
  public String toString() {
   return "name=" + name + ", age=" + age;
  }
 }

執行反序列操作,這次就可以反序列成功了,如下所示: 

Java序列化和反序列化_動力節點Java學院整理 

四、serialVersionUID的取值

  serialVersionUID的取值是Java運行時環境根據類的內部細節自動生成的。如果對類的源代碼作了修改,再重新編譯,新生成的類文件的serialVersionUID的取值有可能也會發生變化。

  類的serialVersionUID的默認值完全依賴于Java編譯器的實現,對于同一個類,用不同的Java編譯器編譯,有可能會導致不同的 serialVersionUID,也有可能相同。為了提高serialVersionUID的獨立性和確定性,強烈建議在一個可序列化類中顯示的定義serialVersionUID,為它賦予明確的值

  顯式地定義serialVersionUID有兩種用途:

    1、 在某些場合,希望類的不同版本對序列化兼容,因此需要確保類的不同版本具有相同的serialVersionUID;

    2、 在某些場合,不希望類的不同版本對序列化兼容,因此需要確保類的不同版本具有不同的serialVersionUID。

延伸 · 閱讀

精彩推薦
Weibo Article 1 Weibo Article 2 Weibo Article 3 Weibo Article 4 Weibo Article 5 Weibo Article 6 Weibo Article 7 Weibo Article 8 Weibo Article 9 Weibo Article 10 Weibo Article 11 Weibo Article 12 Weibo Article 13 Weibo Article 14 Weibo Article 15 Weibo Article 16 Weibo Article 17 Weibo Article 18 Weibo Article 19 Weibo Article 20 Weibo Article 21 Weibo Article 22 Weibo Article 23 Weibo Article 24 Weibo Article 25 Weibo Article 26 Weibo Article 27 Weibo Article 28 Weibo Article 29 Weibo Article 30 Weibo Article 31 Weibo Article 32 Weibo Article 33 Weibo Article 34 Weibo Article 35 Weibo Article 36 Weibo Article 37 Weibo Article 38 Weibo Article 39 Weibo Article 40
主站蜘蛛池模板: 成人在线观看网 | 亚洲国产精品久久久久久 | 免费观看的av | 成人精品久久久 | 91在线免费观看 | 久久se精品一区精品二区 | 欧美一级片毛片免费观看视频 | 日韩一区在线视频 | 欧美精品一区二区三区蜜桃视频 | 亚洲视频中文字幕 | 自拍偷拍专区 | 91精品国产乱码久久久久久 | 国产色| 黄色免费视频 | 午夜成人免费视频 | 一级片av | 91色乱码一区二区三区 | 亚洲成人精品在线观看 | 成人av免费观看 | 丁香五月网久久综合 | a在线看| 97色综合 | 毛片网页 | 免费一级黄色录像 | 亚洲精品一区二区三区精华液 | 亚洲精品视频在线 | 国产第一二区 | 91精品国产综合久久福利软件 | 国产精品成人国产乱一区 | 四虎影视免费看电影 | 天天综合7799精品影视 | 一级免费毛片 | 久久777| 久久久久久国产一级毛片高清版 | 亚洲免费视频一区 | 欧美精品1区2区3区 欧洲一区在线 | 国产精品美女 | 日韩视频中文字幕 | 人人玩人人添人人澡97 | 精品第一页| 国内精品久久久久久久97牛牛 |