一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

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

PHP教程|ASP.NET教程|JAVA教程|ASP教程|

服務器之家 - 編程語言 - JAVA教程 - 深入剖析Java編程中的序列化

深入剖析Java編程中的序列化

2019-12-26 13:28goldensun JAVA教程

這篇文章主要介紹了深入剖析Java編程中的序列化,文中談到了序列化時對象的繼承等各種問題,案例詳盡,強烈推薦!需要的朋友可以參考下

 Java提供一種機制叫做序列化,通過有序的格式或者字節序列持久化java對象,其中包含對象的數據,還有對象的類型,和保存在對象中的數據類型。

所以,如果我們已經序列化了一個對象,那么它可以被讀取并通過對象的類型和其他信息進行反序列化,并最終獲取對象的原型。

ObjectInputStream 和 ObjectOutputStream對象是高級別的流對象,包含序列化和反序列化的方法。

ObjectOutputStream 擁有很多序列化對象的方法,最常用的是:
 

?
1
2
3
4
private void writeObject(ObjectOutputStream os) throws IOException
 {
   
 }

類似的 ObjectInputStream 提供如下方法:
 

?
1
2
3
4
private void readObject(ObjectInputStream is) throws IOException, ClassNotFoundException
{
  
}

那么哪里會需要序列化呢?序列化通常在需要通過網絡傳輸數據,或者保存對象到文件的場合使用。這里說的數據是對象而不是文本。

現在的問題是,我們的網絡架構和硬盤都只能識別二進制和字節,而不能識別Java對象。

序列化就是把Java對象中的value/states翻譯為字節,以便通過網絡傳輸或者保存。另外,反序列化就是通過讀取字節碼,并把它翻譯回java對象。

serialVersionUID概念

serialVersionUID 是用于保證同一個對象(在序列化中會被用到)可以在Deserialization過程中被載入。serialVersionUID 是用于對象的版本控制。你可以參考serialVersionUID in java serialization獲取更多信息。

對于序列化:

步驟如下:

讓我們看一個列子:

在 src->org.arpit.javapostsforlearning 創建Employee.java

1.Employee.java 
 

?
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
package org.arpit.javapostsforlearning;
import java.io.Serializable;
public class Employee implements Serializable{
 
 int employeeId;
 String employeeName;
 String department;
  
 public int getEmployeeId() {
  return employeeId;
 }
 public void setEmployeeId(int employeeId) {
  this.employeeId = employeeId;
 }
 public String getEmployeeName() {
  return employeeName;
 }
 public void setEmployeeName(String employeeName) {
  this.employeeName = employeeName;
 }
 public String getDepartment() {
  return department;
 }
 public void setDepartment(String department) {
  this.department = department;
 }
}

就如你所見的,如果你需要序列化任何類,那么你 必須實現 Serializable 接口 ,這個接口是標記接口(marker interface)。


Java中的標記接口(marker interface)就是一個沒有任何字段或者方法的接口,簡單的來說,java中把空接口叫做標記接口(marker interface)

2.SerializeMain.java
 

?
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
package org.arpit.javapostsforlearning;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
 public class SerializeMain {
 
 /**
 * @author Arpit Mandliya
 */
 public static void main(String[] args) {
 
 Employee emp = new Employee();
 emp.setEmployeeId(101);
 emp.setEmployeeName("Arpit");
 emp.setDepartment("CS");
 try
 {
 FileOutputStream fileOut = new FileOutputStream("employee.ser");
 ObjectOutputStream outStream = new ObjectOutputStream(fileOut);
 outStream.writeObject(emp);
 outStream.close();
 fileOut.close();
 }catch(IOException i)
 {
 i.printStackTrace();
 }
 }
}

對于反序列化:
步驟是

在包src->org.arpit.javapostsforlearning中,創建 DeserializeMain.java
3.DeserializeMain.java
 

?
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
package org.arpit.javapostsforlearning;
import java.io.IOException;
import java.io.ObjectInputStream;
 
public class DeserializeMain {
 /**
 * @author Arpit Mandliya
 */
 public static void main(String[] args) {
 
 Employee emp = null;
  try
  {
   FileInputStream fileIn =new FileInputStream("employee.ser");
   ObjectInputStream in = new ObjectInputStream(fileIn);
   emp = (Employee) in.readObject();
   in.close();
   fileIn.close();
  }catch(IOException i)
  {
   i.printStackTrace();
   return;
  }catch(ClassNotFoundException c)
  {
   System.out.println("Employee class not found");
   c.printStackTrace();
   return;
  }
  System.out.println("Deserialized Employee...");
  System.out.println("Emp id: " + emp.getEmployeeId());
  System.out.println("Name: " + emp.getEmployeeName());
  System.out.println("Department: " + emp.getDepartment());
 }
}


4.運行:
首先運行SerializeMain.java,然后運行 DeserializeMain.java,你會得到如下的結果:
 

?
1
2
3
4
Deserialized Employee...
Emp id: 101
Name: Arpit
Department: CS

就這樣,我們序列化了一個employee對象,并對它進行反序列化。這看起來和簡單,但是如果其中包含對象引用,繼承,那么情況就會變得復雜。接下來讓我們一個接一個的看一下例子,看看如何在各種場合中實現序列化。

案例1 - 如果對象引用了其他對象,那該如何

我們已經看過最簡單的序列化例子,現在看看,如何處理對象中引用了其他對象的場合。我們該如何序列化?引用對象也會被序列化嗎?對的,你不需要顯式的序列化引用對象。當你序列化任何對象,如果它包含引用對象,那么Java序列化會自動序列化該對象的整個對象圖。例如,Employee現在引用了一個address對象,并且Address也引用了其他對象(例如,Home),那么當你序列化Employee對象的時候,所有其他引用對象,例如address和home將會被自動地被序列化。讓我們來創建Address類,并它Address的對象作為引用,添加到employee類中。

Employee.java: 
 

?
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
package org.arpit.javapostsforlearning;
import java.io.Serializable;
 
public class Employee implements Serializable{
 
 int employeeId;
 String employeeName;
 String department;
 Address address;
 
 public int getEmployeeId() {
 return employeeId;
 }
 public void setEmployeeId(int employeeId) {
 this.employeeId = employeeId;
 }
 public String getEmployeeName() {
 return employeeName;
 }
 public void setEmployeeName(String employeeName) {
 this.employeeName = employeeName;
 }
 public String getDepartment() {
 return department;
 }
 public void setDepartment(String department) {
 this.department = department;
 }
 public Address getAddress() {
 return address;
 }
 public void setAddress(Address address) {
 this.address = address;
 }
}

在 org.arpit.javapostsforlearning 包中,創建Address.java
Address.java: 
 

?
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
package org.arpit.javapostsforlearning;
public class Address {
 
 int homeNo;
 String street;
 String city;
 public Address(int homeNo, String street, String city) {
 super();
 this.homeNo = homeNo;
 this.street = street;
 this.city = city;
 }
 public int getHomeNo() {
 return homeNo;
 }
 public void setHomeNo(int homeNo) {
 this.homeNo = homeNo;
 }
 public String getStreet() {
 return street;
 }
 public void setStreet(String street) {
 this.street = street;
 }
 public String getCity() {
 return city;
 }
 public void setCity(String city) {
 this.city = city;
 }
}

在包 org.arpit.javapostsforlearning中,創建SerializeDeserializeMain.java
SerializeDeserializeMain.java:
 

?
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
package org.arpit.javapostsforlearning;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
 
public class SerializeDeserializeMain {
 /**
 * @author Arpit Mandliya
 */
 public static void main(String[] args) {
 
 Employee emp = new Employee();
 emp.setEmployeeId(101);
 emp.setEmployeeName("Arpit");
 emp.setDepartment("CS");
 Address address=new Address(88,"MG road","Pune");
 emp.setAddress(address);
 //Serialize
 try
 {
 FileOutputStream fileOut = new FileOutputStream("employee.ser");
 ObjectOutputStream outStream = new ObjectOutputStream(fileOut);
 outStream.writeObject(emp);
 outStream.close();
 fileOut.close();
 }catch(IOException i)
 {
 i.printStackTrace();
 }
 
 //Deserialize
 emp = null;
 try
 {
 FileInputStream fileIn =new FileInputStream("employee.ser");
 ObjectInputStream in = new ObjectInputStream(fileIn);
 emp = (Employee) in.readObject();
 in.close();
 fileIn.close();
 }catch(IOException i)
 {
 i.printStackTrace();
 return;
 }catch(ClassNotFoundException c)
 {
 System.out.println("Employee class not found");
 c.printStackTrace();
 return;
 }
 System.out.println("Deserialized Employee...");
 System.out.println("Emp id: " + emp.getEmployeeId());
 System.out.println("Name: " + emp.getEmployeeName());
 System.out.println("Department: " + emp.getDepartment());
 address=emp.getAddress();
 System.out.println("City :"+address.getCity());
 }
}

運行它:
當你運行SerializeDeserializeMain.java。你會得到這樣的結果:
 

?
1
2
3
4
5
6
7
java.io.NotSerializableException: org.arpit.javapostsforlearning.Address
 at java.io.ObjectOutputStream.writeObject0(Unknown Source)
 at java.io.ObjectOutputStream.defaultWriteFields(Unknown Source)
 at java.io.ObjectOutputStream.writeSerialData(Unknown Source)
 at java.io.ObjectOutputStream.writeOrdinaryObject(Unknown Source)
 at java.io.ObjectOutputStream.writeObject0(Unknown Source)
 at java.io.ObjectOutputStream.writeObject(Unknown Source)

我們將解釋哪里出錯了。我忘記了說,Address 類也必須是serializable。那么Address類必須繼承serialzable接口。

Address.java:
 

?
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
import java.io.Serializable;
 
public class Address implements Serializable{
 
 int homeNo;
 String street;
 String city;
 public Address(int homeNo, String street, String city) {
 super();
 this.homeNo = homeNo;
 this.street = street;
 this.city = city;
 }
 public int getHomeNo() {
 return homeNo;
 }
 public void setHomeNo(int homeNo) {
 this.homeNo = homeNo;
 }
 public String getStreet() {
 return street;
 }
 public void setStreet(String street) {
 this.street = street;
 }
 public String getCity() {
 return city;
 }
 public void setCity(String city) {
 this.city = city;
 }
}

再次運行:
當你再次運行SerializeDeserializeMain.java。你可以得到如下的結果
 

?
1
2
3
4
5
Deserialized Employee...
Emp id: 101
Name: Arpit
Department: CS
City :Pune

案例2:如果我們不能訪問引用對象的源代碼(例如,你不能訪問上面的Address類的源碼)

如果我們不能訪問到address類,那么我們該如何在Address類中實現serializable 接口?是否有另外的途徑來實現呢?對的,你可以創建另外一個類,并繼承Address,然后讓它繼承serializable 接口,但是對于下面的情況,這個方案會失敗:

    如果引用類被定義為final
    如果引用類引用了另外一個非可序列化的對象

那么,我們該如何序列化Employee對象?解決的辦法是,標記transient。如果你不需要序列化任何字段,只需把它標記為transient。
 
transient Address address
在Employee類中,標記了address為transient之后,運行程序。你會得到nullPointerException,因為在反序列化過程中,Address引用將會是null。


案例3 - 如果我仍然需要保存引用對象的狀態呢?(例如address對象)

如果你在反序列化過程中,標記了address為transient,它將會返回null結果。但是如果你仍然需要保存它的狀態,你就需要序列化address對象。 Java序列化提供一個機制,如果你有特定簽名的private方法,那么它們就會在序列化和反序列化過程中被調用,所以我們將重寫Employee類的writeObject和readObject方法,然后它們就會在Employee對象序列化/反序列化過程中被調用。

Employee.java:

?
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
package org.arpit.javapostsforlearning;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
 
public class Employee implements Serializable{
 
 int employeeId;
 String employeeName;
 String department;
 transient Address address;
 
 public int getEmployeeId() {
 return employeeId;
 }
 public void setEmployeeId(int employeeId) {
 this.employeeId = employeeId;
 }
 public String getEmployeeName() {
 return employeeName;
 }
 public void setEmployeeName(String employeeName) {
 this.employeeName = employeeName;
 }
 public String getDepartment() {
 return department;
 }
 public void setDepartment(String department) {
 this.department = department;
 }
 public Address getAddress() {
 return address;
 }
 public void setAddress(Address address) {
 this.address = address;
 }
 
 private void writeObject(ObjectOutputStream os) throws IOException, ClassNotFoundException
 {
 try {
 os.defaultWriteObject();
 os.writeInt(address.getHomeNo());
 os.writeObject(address.getStreet());
 os.writeObject(address.getCity());
 }
 catch (Exception e)
 { e.printStackTrace(); }
 }
 
 private void readObject(ObjectInputStream is) throws IOException, ClassNotFoundException
 {
 try {
 is.defaultReadObject();
 int homeNo=is.readInt();
 String street=(String) is.readObject();
 String city=(String) is.readObject();
 address=new Address(homeNo,street,city);
 
 } catch (Exception e) { e.printStackTrace(); }
 }
}

另外有一點需要牢記的,ObjectInputStream讀取數據的順序和ObjectOutputStream寫入數據的順序是一致的.

在包org.arpit.javapostsforlearning 中創建Address.java
Address.java: 
 

?
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
package org.arpit.javapostsforlearning;
import java.io.Serializable;
 
public class Address {
 
 int homeNo;
 String street;
 String city;
 
 
 public Address(int homeNo, String street, String city) {
 super();
 this.homeNo = homeNo;
 this.street = street;
 this.city = city;
 }
 public int getHomeNo() {
 return homeNo;
 }
 public void setHomeNo(int homeNo) {
 this.homeNo = homeNo;
 }
 public String getStreet() {
 return street;
 }
 public void setStreet(String street) {
 this.street = street;
 }
 public String getCity() {
 return city;
 }
 public void setCity(String city) {
 this.city = city;
 }
}

在包org.arpit.javapostsforlearning中創建SerializeDeserializeMain.java
SerializeDeserializeMain.java:
 

?
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
package org.arpit.javapostsforlearning;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
 
public class SerializeDeserializeMain {
 /**
 * @author Arpit Mandliya
 */
 public static void main(String[] args) {
 
 Employee emp = new Employee();
 emp.setEmployeeId(101);
 emp.setEmployeeName("Arpit");
 emp.setDepartment("CS");
 Address address=new Address(88,"MG road","Pune");
 emp.setAddress(address);
 //Serialize
 try
 {
 FileOutputStream fileOut = new FileOutputStream("employee.ser");
 ObjectOutputStream outStream = new ObjectOutputStream(fileOut);
 outStream.writeObject(emp);
 outStream.close();
 fileOut.close();
 }catch(IOException i)
 {
 i.printStackTrace();
 }
 
 //Deserialize
 emp = null;
 try
 {
 FileInputStream fileIn =new FileInputStream("employee.ser");
 ObjectInputStream in = new ObjectInputStream(fileIn);
 emp = (Employee) in.readObject();
 in.close();
 fileIn.close();
 }catch(IOException i)
 {
 i.printStackTrace();
 return;
 }catch(ClassNotFoundException c)
 {
 System.out.println("Employee class not found");
 c.printStackTrace();
 return;
 }
 System.out.println("Deserialized Employee...");
 System.out.println("Emp id: " + emp.getEmployeeId());
 System.out.println("Name: " + emp.getEmployeeName());
 System.out.println("Department: " + emp.getDepartment());
 address=emp.getAddress();
 System.out.println("City :"+address.getCity());
 }
}

運行 :
當你運行SerializeDeserializeMain.java.你會得到如下的結果: 
 

?
1
2
3
4
5
Deserialized Employee...
Emp id: 101
Name: Arpit
Department: CS
City :Pune

現在我們就得到了address對象的狀態,就如它被序列化前的一樣。

序列化中的繼承:

現在我們看看繼承是如何影響序列化的。不管父類是不是可序列化,這將引出很多個例子。如果父類是非可序列化的,我們將如何處理,并且它是如何工作的。讓我們看看例子。

我們將創建一個Person.java,作為 Employee的父類。

案例4: 如果父類是可序列化的

如果父類可序列化,那么所有的繼承類將是可序列化的。

案例5: 如果父類為非可序列化呢?

如果父類為非可序列化的 ,那么我們的處理辦法會很不一樣。

    如果父類為非可序列化的,那么它必然不會有參數構造函數。

Person.java 
 

?
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
package org.arpit.javapostsforlearning;
public class Person {
 
 String name="default";
 String nationality;
 
 public Person()
 {
 System.out.println("Person:Constructor");
 }
 
 public Person(String name, String nationality) {
 super();
 this.name = name;
 this.nationality = nationality;
 }
 
 public String getName() {
 return name;
 }
 
 public void setName(String name) {
 this.name = name;
 }
 
 public String getNationality() {
 return nationality;
 }
 
 public void setNationality(String nationality) {
 this.nationality = nationality;
 }
 
}

在包org.arpit.javapostsforlearning 中創建Employee.java
Employee.java:

 

?
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
package org.arpit.javapostsforlearning;
import java.io.Serializable;
 
public class Employee extends Person implements Serializable{
 
 int employeeId;
 String department;
 
 public Employee(int employeeId,String name,String department,String nationality)
 {
 super(name,nationality);
 this.employeeId=employeeId;
 this.department=department;
 System.out.println("Employee:Constructor");
 }
 
 public int getEmployeeId() {
 return employeeId;
 }
 public void setEmployeeId(int employeeId) {
 this.employeeId = employeeId;
 }
 
 public String getDepartment() {
 return department;
 }
 public void setDepartment(String department) {
 this.department = department;
 }
}

在org.arpit.javapostsforlearning包中創建SerializeDeserializeMain.java

SerializeDeserializeMain.java:

?
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
package org.arpit.javapostsforlearning;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
 
public class SerializeDeserializeMain {
 
 /**
 * @author Arpit Mandliya
 */
 public static void main(String[] args) {
 
 //Serialize
 Employee emp = new Employee(101,"Arpit","CS","Indian");
 System.out.println("Before serializing");
 System.out.println("Emp id: " + emp.getEmployeeId());
 System.out.println("Name: " + emp.getName());
 System.out.println("Department: " + emp.getDepartment());
 System.out.println("Nationality: " + emp.getNationality());
 System.out.println("************");
 System.out.println("Serializing");
 try
 {
 FileOutputStream fileOut = new FileOutputStream("employee.ser");
 ObjectOutputStream outStream = new ObjectOutputStream(fileOut);
 outStream.writeObject(emp);
 outStream.close();
 fileOut.close();
 }catch(IOException i)
 {
 i.printStackTrace();
 }
 
 //Deserialize
 System.out.println("************");
 System.out.println("Deserializing");
 emp = null;
 try
 {
 FileInputStream fileIn =new FileInputStream("employee.ser");
 ObjectInputStream in = new ObjectInputStream(fileIn);
 emp = (Employee) in.readObject();
 in.close();
 fileIn.close();
 }catch(IOException i)
 {
 i.printStackTrace();
 return;
 }catch(ClassNotFoundException c)
 {
 System.out.println("Employee class not found");
 c.printStackTrace();
 return;
 }
 System.out.println("After serializing");
 System.out.println("Emp id: " + emp.getEmployeeId());
 System.out.println("Name: " + emp.getName());
 System.out.println("Department: " + emp.getDepartment());
 System.out.println("Nationality: " + emp.getNationality());
 }
}

運行:

當你運行SerializeDeserializeMain.java后,你會得到如下的輸出,如果父類是非可序列化的,那么在反序列化過程中,所有繼承于父類的實例變量值,將會通過調用非序列化構造函數來初始化。 這里 name繼承于person,所以在反序列化過程中,name將會被初始化為默認值。


案例6 - 如果父類是可序列化,但你不需要繼承類為可序列化

如果你不希望繼承類為可序列化,那么你需要實現 writeObject() 和readObject() 方法,并且需要拋出NotSerializableException 異常。

案例7 - 可否序列化靜態變量?

不能。因為靜態變量是類級別的,不是對象級別的,當你序列化一個對象的時候,是不能序列化靜態變量。


總結:

  •     序列化是java對象的values/states轉化為字節并在網絡中傳輸或者保存它的過程。另外反序列化是把字節碼翻譯為對應的對象的過程。
  •     序列化的好處是,JVM的獨立性,也就是說,一個對象可以在一個平臺中被序列化,然后在另外一個不同的平臺反序列化。
  •     如果你需要序列化任何對象,你必須實現標記接口Serializable。
  •     Java中的標記接口(Marker interface)就是沒有字段或者方法的接口,或者更簡單的說,空接口
  •     serialVersionUID 是用于保證同一個對象(在序列化中會被用到)可以在Deserialization過程中被載入。serialVersionUID 是用于對象的版本控制。
  •     當你需要序列化任何包含引用對象的對象,那么Java會自動序列化該對象的整個對象圖。
  •     如果你不希望序列化某個字段,你可以標記它為trasient
  •     如果父類為可序列化,那么它的繼承類也將是可序列化的。
  •     如果父類為非可序列化,那么在反序列化過程中,所有繼承于父類的實例變量值將會通過調用非可序列化的構造器來初始化。
  •     如果你需希望子類為可序列化的,那么你需要實現writeObject() 和 readObject() 方法,并在這兩個方法中拋出NotSerializableException異常
  •     你不能序列化靜態變量。

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: xxoo做爰猛烈动态 | 国产精品久久久久毛片真精品 | 海绵宝宝第二季全集免费观看 | 日韩久久中文字幕 | 国产伦精品一区二区三区女 | 日本性生活免费看 | 青青草影院在线观看 | 亚洲区精品 | 校园肉文高h | 91亚洲专区 | 美女禁18| 奇米影视在线视频8888 | 我与么公激情性完整视频 | 免费午夜剧场 | www.亚洲视频.com | 91制片厂制作传媒网站破解 | 午夜AV亚洲一码二中文字幕青青 | 日韩在线视频免费观看 | 亚洲欧美日韩综合一区久久 | 日本h乱淫动漫在线观看 | 国产成人高清精品免费5388密 | 奇米色7777 | 免费人成在线观看69式小视频 | 亚洲 欧美 清纯 校园 另类 | 久久永久影院免费 | 日本美女xx| 亚洲大尺码 | 狠狠干2017 | 亚洲国产欧美在线人成 | 亚洲上最大成网人站4438 | 国内精品一区二区三区东京 | 我要看黄色毛片 | 亚洲国产精品嫩草影院久久 | 特黄特色大片免费视频播放 | 99视频全部看免费观 | 免费国产成人高清视频网站 | 日本一区二区视频在线观看 | 成人小视频在线观看免费 | 国产日韩精品一区二区三区 | 成年视频在线播放 | 小浪妇奶真大水多 |