精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

面試官:詳細說說你對序列化的理解

開發 前端
在Java語言中,程序運行的時候,會產生很多對象,而對象信息也只是在程序運行的時候才在內存中保持其狀態,一旦程序停止,內存釋放,對象也就不存在了。

 [[355611]]

本文主要內容

 

背景

在Java語言中,程序運行的時候,會產生很多對象,而對象信息也只是在程序運行的時候才在內存中保持其狀態,一旦程序停止,內存釋放,對象也就不存在了。

怎么能讓對象永久的保存下來呢?--------對象序列化 。

何為序列化和反序列化?

  • 序列化:對象到IO數據流

 

  • 反序列化:IO數據流到對象

 

有哪些使用場景?

Java平臺允許我們在內存中創建可復用的Java對象,但一般情況下,只有當JVM處于運行時,這些對象才可能存在,即,這些對象的生命周期不會比JVM的生命周期更長。但在現實應用中,就可能要求在JVM停止運行之后能夠保存(持久化)指定的對象,并在將來重新讀取被保存的對象。Java對象序列化就能夠幫助我們實現該功能。

使用Java對象序列化,在保存對象時,會把其狀態保存為一組字節,在未來,再將這些字節組裝成對象。必須注意地是,對象序列化保存的是對象的"狀態",即它的成員變量。由此可知,對象序列化不會關注類中的靜態變量。

除了在持久化對象時會用到對象序列化之外,當使用RMI(遠程方法調用),或在網絡中傳遞對象時,都會用到對象序列化。

Java序列化API為處理對象序列化提供了一個標準機制,該API簡單易用。

很多框架中都有用到,比如典型的dubbo框架中使用了序列化。

序列化有什么作用?

序列化機制允許將實現序列化的Java對象轉換位字節序列,這些字節序列可以保存在磁盤上,或通過網絡傳輸,以達到以后恢復成原來的對象。序列化機制使得對象可以脫離程序的運行而獨立存在。

序列化實現方式

Java語言中,常見實現序列化的方式有兩種:

  • 實現Serializable接口
  • 實現Externalizable接口

下面我們就來詳細的說說這兩種實現方式。

  • 實現Serializable接口

創建一個User類實現Serializable接口 ,實現序列化,大致步驟為:

  1. 對象實體類實現Serializable 標記接口。
  2. 創建序列化輸出流對象ObjectOutputStream,該對象的創建依賴于其它輸出流對象,通常我們將對象序列化為文件存儲,所以這里用文件相關的輸出流對象 FileOutputStream。
  3. 通過ObjectOutputStream 的 writeObject()方法將對象序列化為文件。
  4. 關閉流。

以下就是code:

  1. package com.tian.my_code.test.clone; 
  2.      
  3.     import java.io.FileOutputStream; 
  4.     import java.io.IOException; 
  5.     import java.io.ObjectOutputStream; 
  6.     import java.io.Serializable
  7.      
  8.     public class User implements Serializable { 
  9.         private int age; 
  10.         private String name
  11.      
  12.         public User() { 
  13.         } 
  14.      
  15.         public User(int age, String name) { 
  16.             this.age = age; 
  17.             this.name = name
  18.         } 
  19.         //set get省略 
  20.         public static void main(String[] args) { 
  21.             try { 
  22.                 ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("user.txt")); 
  23.                 User user=new User(22,"老田"); 
  24.                 objectOutputStream.writeObject(user); 
  25.             } catch (IOException e) { 
  26.                 e.printStackTrace(); 
  27.             } 
  28.         } 
  29.     } 

創建一個User對象,然后把User對象保存的user.txt中了。

反序列化

大致有以下三個步驟:

  1. 創建輸入流對象ObjectOutputStream。同樣依賴于其它輸入流對象,這里是文件輸入流 FileInputStream。
  2. 通過 ObjectInputStream 的 readObject()方法,將文件中的對象讀取到內存。
  3. 關閉流。

下面我們再進行反序列化code:

  1. package com.tian.my_code.test.clone; 
  2.      
  3.     import java.io.*; 
  4.      
  5.     public class SeriTest { 
  6.         public static void main(String[] args) { 
  7.             try { 
  8.                 ObjectInputStream ois = new ObjectInputStream(new FileInputStream("user.txt")); 
  9.                 User user=(User) ois.readObject(); 
  10.                 System.out.println(user.getName()); 
  11.             } catch (Exception e) { 
  12.                 e.printStackTrace(); 
  13.             } 
  14.         } 
  15.     } 

運行這段代碼,輸出結果:

 

使用IDEA打開user.tst文件:

 

使用編輯器16機制查看

 

關于文件內容咱們就不用太關心了,繼續說我們的重點。

序列化是把User對象存放到文件里了,然后反序列化就是讀取文件內容并創建對象。

A端把對象User保存到文件user.txt中,B端就可以通過網絡或者其他方式讀取到這個文件,再進行反序列化,獲得A端創建的User對象。

拓展

如果B端拿到的User屬性如果有變化呢?比如說:增加一個字段

  1. private String address; 

再次進行反序列化就會報錯

 

添加serialVersionUID

  1. package com.tian.my_code.test.clone; 
  2.      
  3.     import java.io.FileOutputStream; 
  4.     import java.io.IOException; 
  5.     import java.io.ObjectOutputStream; 
  6.     import java.io.Serializable
  7.      
  8.     public class User implements Serializable
  9.         private static final long serialVersionUID = 2012965743695714769L; 
  10.         private int age; 
  11.         private String name
  12.      
  13.         public User() { 
  14.         } 
  15.      
  16.         public User(int age, String name) { 
  17.             this.age = age; 
  18.             this.name = name
  19.         } 
  20.      
  21.         // set get   省略 
  22.      
  23.         public static void main(String[] args) { 
  24.             try { 
  25.                 ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("user.txt")); 
  26.                 User user=new User(22,"老田"); 
  27.                 objectOutputStream.writeObject(user); 
  28.             } catch (IOException e) { 
  29.                 e.printStackTrace(); 
  30.             } 
  31.         } 
  32.     } 

再次執行反序列化,運行結果正常

 

然后我們再次加上字段和對應的get/set方法

  1. private String address; 

再次執行反序列化

 

反序列化成功。

如果可序列化類未顯式聲明 serialVersionUID,則序列化運行時將基于該類的各個方面計算該類的默認 serialVersionUID 值,如“Java(TM) 對象序列化規范”中所述。

不過,強烈建議 所有可序列化類都顯式聲明 serialVersionUID 值,原因是計算默認的 serialVersionUID對類的詳細信息具有較高的敏感性,根據編譯器實現的不同可能千差萬別,這樣在反序列化過程中可能會導致意外的 InvalidClassException。

因此,為保證 serialVersionUID值跨不同 Java 編譯器實現的一致性,序列化類必須聲明一個明確的 serialVersionUID值。

強烈建議使用 private 修飾符顯示聲明 serialVersionUID(如果可能),原因是這種聲明僅應用于直接聲明類 -- serialVersionUID字段作為繼承成員沒有用處。數組類不能聲明一個明確的 serialVersionUID,因此它們總是具有默認的計算值,但是數組類沒有匹配 serialVersionUID值的要求。

所以,盡量顯示的聲明,這樣序列化的類即使有字段的修改,因為 serialVersionUID的存在,也能保證反序列化成功。保證了更好的兼容性。

IDEA中如何快捷添加serialVersionUID?

 

我們的類實現Serializable接口,鼠標放在類上,Alt+Enter鍵就可以添加了。

實現Externalizable接口

通過實現Externalizable接口,必須實現writeExternal、readExternal方法。

  1. @Override 
  2. public void writeExternal(ObjectOutput out) throws IOException { 
  3. @Override 
  4. public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { 
  5.      

Externalizable是Serializable的子接口。

public interface Externalizable extends java.io.Serializable {

繼續使用前面的User,代碼進行改造:

  1. package com.tian.my_code.test.clone; 
  2.      
  3.     import java.io.*; 
  4.      
  5.     public class User implements Externalizable { 
  6.         private int age; 
  7.         private String name
  8.      
  9.         public User() { 
  10.         } 
  11.      
  12.         public User(int age, String name) { 
  13.             this.age = age; 
  14.             this.name = name
  15.         } 
  16.      
  17.         //set get 
  18.      
  19.      
  20.         public static void main(String[] args) { 
  21.             try { 
  22.                 ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("user.txt")); 
  23.                 User user = new User(22, "老田"); 
  24.                 objectOutputStream.writeObject(user); 
  25.             } catch (IOException e) { 
  26.                 e.printStackTrace(); 
  27.             } 
  28.         } 
  29.      
  30.         @Override 
  31.         public void writeExternal(ObjectOutput out) throws IOException { 
  32.             //將name反轉后寫入二進制流 
  33.             StringBuffer reverse = new StringBuffer(name).reverse(); 
  34.             out.writeObject(reverse); 
  35.             out.writeInt(age); 
  36.         } 
  37.      
  38.         @Override 
  39.         public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { 
  40.             //將讀取的字符串反轉后賦值給name實例變量 
  41.             this.name = ((StringBuffer) in.readObject()).reverse().toString(); 
  42.             //將讀取到的int類型值付給age 
  43.             this.age = in.readInt(); 
  44.         } 
  45.     } 
  46.      

執行序列化,然后再次執行反序列化,輸出:

 

注意

Externalizable接口不同于Serializable接口,實現此接口必須實現接口中的兩個方法實現自定義序列化,這是強制性的;特別之處是必須提供public的無參構造器,因為在反序列化的時候需要反射創建對象。

兩種方式對比

下圖為兩種實現方式的對比:

 

序列化只有兩種方式嗎?

當然不是。根據序列化的定義,不管通過什么方式,只要你能把內存中的對象轉換成能存儲或傳輸的方式,又能反過來恢復它,其實都可以稱為序列化。因此,我們常用的Fastjson、Jackson等第三方類庫將對象轉成Json格式文件,也可以算是一種序列化,用JAXB實現XML格式文件輸出,也可以算是序列化。所以,千萬不要被思維局限,其實現實當中我們進行了很多序列化和反序列化的操作,涉及不同的形態、數據格式等。

序列化算法

  • 所有保存到磁盤的對象都有一個序列化編碼號。
  • 當程序試圖序列化一個對象時,會先檢查此對象是否已經序列化過,只有此對象從未(在此虛擬機)被序列化過,才會將此對象序列化為字節序列輸出。
  • 如果此對象已經序列化過,則直接輸出編號即可。

自定義序列化

有些時候,我們有這樣的需求,某些屬性不需要序列化。使用transient關鍵字選擇不需要序列化的字段。

繼續使用前面的代碼進行改造,在age字段上添加transient修飾:

  1.  package com.tian.my_code.test.clone; 
  2.      
  3.     import java.io.FileOutputStream; 
  4.     import java.io.IOException; 
  5.     import java.io.ObjectOutputStream; 
  6.     import java.io.Serializable
  7.      
  8.     public class User implements Serializable
  9.         private transient int age; 
  10.         private String name
  11.      
  12.      
  13.         public User() { 
  14.         } 
  15.      
  16.         public User(int age, String name) { 
  17.             this.age = age; 
  18.             this.name = name
  19.         } 
  20.      
  21.         public int getAge() { 
  22.             return age; 
  23.         } 
  24.      
  25.         public void setAge(int age) { 
  26.             this.age = age; 
  27.         } 
  28.      
  29.         public String getName() { 
  30.             return name
  31.         } 
  32.      
  33.         public void setName(String name) { 
  34.             this.name = name
  35.         } 
  36.      
  37.         public static void main(String[] args) { 
  38.             try { 
  39.                 ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("user.txt")); 
  40.                 User user=new User(22,"老田"); 
  41.                 objectOutputStream.writeObject(user); 
  42.             } catch (IOException e) { 
  43.                 e.printStackTrace(); 
  44.             } 
  45.         } 
  46.     } 
  47.     ``` 
  48.  
  49. 序列化,然后進行反序列化: 
  50. ```java 
  51.     package com.tian.my_code.test.clone; 
  52.      
  53.     import java.io.*; 
  54.      
  55.     public class SeriTest { 
  56.         public static void main(String[] args) { 
  57.             try { 
  58.                 ObjectInputStream ois = new ObjectInputStream(new FileInputStream("user.txt")); 
  59.                 User user=(User) ois.readObject(); 
  60.                 System.out.println(user.getName()); 
  61.                 System.out.println(user.getAge()); 
  62.             } catch (Exception e) { 
  63.                 e.printStackTrace(); 
  64.             } 
  65.         } 
  66.     } 

運行輸出:

 

從輸出我們看到,使用transient修飾的屬性,Java序列化時,會忽略掉此字段,所以反序列化出的對象,被transient修飾的屬性是默認值。

對于引用類型,值是null;基本類型,值是0;boolean類型,值是false。

探索

到此序列化內容算講完了,但是,如果只停留在這個層面,是無法應對實際工作中的問題的。

比如模型對象持有其它對象的引用怎么處理,引用類型如果是復雜些的集合類型怎么處理?

上面的User中持有String引用類型的,照樣序列化沒問題,那么如果是我們自定義的引用類呢?

比如下面的場景:

  1. package com.tian.my_code.test.clone; 
  2.      
  3.     public class UserAddress { 
  4.         private int provinceCode; 
  5.         private int cityCode; 
  6.      
  7.         public UserAddress() { 
  8.         } 
  9.      
  10.         public UserAddress(int provinceCode, int cityCode) { 
  11.             this.provinceCode = provinceCode; 
  12.             this.cityCode = cityCode; 
  13.         } 
  14.      
  15.         public int getProvinceCode() { 
  16.             return provinceCode; 
  17.         } 
  18.      
  19.         public void setProvinceCode(int provinceCode) { 
  20.             this.provinceCode = provinceCode; 
  21.         } 
  22.      
  23.         public int getCityCode() { 
  24.             return cityCode; 
  25.         } 
  26.      
  27.         public void setCityCode(int cityCode) { 
  28.             this.cityCode = cityCode; 
  29.         } 
  30.     } 

然后在User中添加一個UserAddress的屬性:

  1. package com.tian.my_code.test.clone; 
  2.      
  3.     import java.io.FileOutputStream; 
  4.     import java.io.IOException; 
  5.     import java.io.ObjectOutputStream; 
  6.     import java.io.Serializable
  7.      
  8.     public class User implements Serializable
  9.         private static final long serialVersionUID = -2445226500651941044L; 
  10.         private int age; 
  11.         private String name
  12.         private UserAddress userAddress; 
  13.      
  14.         public User() { 
  15.         } 
  16.      
  17.         public User(int age, String name) { 
  18.             this.age = age; 
  19.             this.name = name
  20.         } 
  21.         //get set 
  22.          
  23.         public static void main(String[] args) { 
  24.             try { 
  25.                 ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("user.txt")); 
  26.                 User user=new User(22,"老田"); 
  27.                 UserAddress userAddress=new UserAddress(10001,10001001); 
  28.                 user.setUserAddress(userAddress); 
  29.                 objectOutputStream.writeObject(user); 
  30.             } catch (IOException e) { 
  31.                 e.printStackTrace(); 
  32.             } 
  33.         } 
  34.     } 

運行上面代碼:

 

拋出了 java.io.NotSerializableException 異常。很明顯在告訴我們,UserAddress沒有實現序列化接口。待UserAddress類實現序列化接口后:

  1. package com.tian.my_code.test.clone; 
  2.      
  3.     import java.io.Serializable
  4.      
  5.     public class UserAddress implements Serializable { 
  6.         private static final long serialVersionUID = 5128703296815173156L; 
  7.         private int provinceCode; 
  8.         private int cityCode; 
  9.      
  10.         public UserAddress() { 
  11.         } 
  12.      
  13.         public UserAddress(int provinceCode, int cityCode) { 
  14.             this.provinceCode = provinceCode; 
  15.             this.cityCode = cityCode; 
  16.         } 
  17.         //get set 
  18.     } 

再次運行,正常不報錯了。

反序列化代碼:

  1. package com.tian.my_code.test.clone; 
  2.      
  3.     import java.io.*; 
  4.      
  5.     public class SeriTest { 
  6.         public static void main(String[] args) { 
  7.             try { 
  8.                 ObjectInputStream ois = new ObjectInputStream(new FileInputStream("user.txt")); 
  9.                 User user=(User) ois.readObject(); 
  10.                 System.out.println(user.getName()); 
  11.                 System.out.println(user.getAge()); 
  12.                 System.out.println(user.getUserAddress().getProvinceCode()); 
  13.                 System.out.println(user.getUserAddress().getCityCode()); 
  14.             } catch (Exception e) { 
  15.                 e.printStackTrace(); 
  16.             } 
  17.         } 
  18.     } 

運行結果:

 

典型運用場景

  1. public final class String implements java.io.Serializable, Comparable<String>, CharSequence { 
  2.        private static final long serialVersionUID = -6849794470754667710L; 
  3.    } 
  4.    public class HashMap<K,V> extends AbstractMap<K,V>  implements Map<K,V>, Cloneable, Serializable { 
  5.        private static final long serialVersionUID = 362498820763181265L; 
  6.    } 
  7.    public class ArrayList<E> extends AbstractList<E>  implements List<E>, RandomAccess, Cloneable, java.io.Serializable
  8.        private static final long serialVersionUID = 8683452581122892189L; 
  9.    } 
  10.    ..... 

很多常用類都實現了序列化接口。

再次拓展

上面說的transient 反序列化的時候是默認值,但是你會發現,幾種常用集合類ArrayList、HashMap、LinkedList等數據存儲字段,竟然都被 transient 修飾了,然而在實際操作中我們用集合類型存儲的數據卻可以被正常的序列化和反序列化?

 

真相當然還是在源碼里。實際上,各個集合類型對于序列化和反序列化是有單獨的實現的,并沒有采用虛擬機默認的方式。這里以 ArrayList中的序列化和反序列化源碼部分為例分析:

  1. private void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException{ 
  2.             int expectedModCount = modCount; 
  3.             //序列化當前ArrayList中非transient以及非靜態字段 
  4.             s.defaultWriteObject(); 
  5.             //序列化數組實際個數 
  6.             s.writeInt(size); 
  7.             // 逐個取出數組中的值進行序列化 
  8.             for (int i=0; i<size; i++) { 
  9.                 s.writeObject(elementData[i]); 
  10.             } 
  11.             //防止在并發的情況下對元素的修改 
  12.             if (modCount != expectedModCount) { 
  13.                 throw new ConcurrentModificationException(); 
  14.             } 
  15.         } 
  16.      
  17.         private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException { 
  18.             elementData = EMPTY_ELEMENTDATA; 
  19.             // 反序列化非transient以及非靜態修飾的字段,其中包含序列化時的數組大小 size 
  20.             s.defaultReadObject(); 
  21.             // 忽略的操作 
  22.             s.readInt(); // ignored 
  23.             if (size > 0) { 
  24.                 // 容量計算 
  25.                 int capacity = calculateCapacity(elementData, size); 
  26.                 SharedSecrets.getJavaOISAccess().checkArray(s, Object[].class, capacity); 
  27.                 //檢測是否需要對數組擴容操作 
  28.                 ensureCapacityInternal(size); 
  29.                 Object[] a = elementData; 
  30.                 // 按順序反序列化數組中的值 
  31.                 for (int i=0; i<size; i++) { 
  32.                     a[i] = s.readObject(); 
  33.                 } 
  34.             } 
  35.         } 

讀源碼可以知道,ArrayList的序列化和反序列化主要思路就是根據集合中實際存儲的元素個數來進行操作,這樣做估計是為了避免不必要的空間浪費(因為ArrayList的擴容機制決定了,集合中實際存儲的元素個數肯定比集合的可容量要小)。為了驗證,我們可以在單元測試序列化和返序列化的時候,在ArrayLIst的兩個方法中打上斷點,以確認這兩個方法在序列化和返序列化的執行流程中(截圖為反序列化過程):

原來,我們之前自以為集合能成功序列化也只是簡單的實現了標記接口都只是表象,表象背后有各個集合類有不同的深意。所以,同樣的思路,讀者朋友可以自己去分析下 HashMap以及其它集合類中自行控制序列化和反序列化的個中門道了,感興趣的小伙伴可以自行去查看一番。

序列化注意事項

1、序列化時,只對對象的狀態進行保存,而不管對象的方法;

2、當一個父類實現序列化,子類自動實現序列化,不需要顯式實現Serializable接口;

3、當一個對象的實例變量引用其他對象,序列化該對象時也把引用對象進行序列化;

4、并非所有的對象都可以序列化,至于為什么不可以,有很多原因了,比如:

安全方面的原因,比如一個對象擁有private,public等field,對于一個要傳輸的對象,比如寫到文件,或者進行RMI傳輸等等,在序列化進行傳輸的過程中,這個對象的private等域是不受保護的;

資源分配方面的原因,比如socket,thread類,如果可以序列化,進行傳輸或者保存,也無法對他們進行重新的資源分配,而且,也是沒有必要這樣實現;

5、聲明為static和transient類型的成員數據不能被序列化。因為static代表類的狀態,transient代表對象的臨時數據。

6、序列化運行時使用一個稱為 serialVersionUID 的版本號與每個可序列化類相關聯,該序列號在反序列化過程中用于驗證序列化對象的發送者和接收者是否為該對象加載了與序列化兼容的類。為它賦予明確的值。顯式地定義serialVersionUID有兩種用途:

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

7、Java有很多基礎類已經實現了serializable接口,比如String,Vector等。但是也有一些沒有實現serializable接口的;

8、如果一個對象的成員變量是一個對象,那么這個對象的數據成員也會被保存!這是能用序列化解決深拷貝的重要原因;

總結

什么是序列化?序列化Java中常用實現方式有哪些?兩種實現序列化方式的對比,序列化算法?如何自定義序列化?Java集合框架中序列化是如何實現的?

這幾個點如果沒有get到,麻煩請再次閱讀,或者加我微信進群里大家一起聊。

參考:

  1. cnblogs.com/9dragon/p/10901448.html oschina.net/translate/serialization-in-java 

本文轉載自微信公眾號「 Java后端技術全棧」,可以通過以下二維碼關注。轉載本文請聯系 Java后端技術全棧公眾號。

 

責任編輯:武曉燕 來源: Java后端技術全棧
相關推薦

2022-02-21 17:24:18

序列化對象存儲

2021-11-25 10:18:42

RESTfulJava互聯網

2021-08-09 07:47:40

Git面試版本

2020-12-01 08:47:36

Java異常開發

2020-06-12 15:50:56

options前端服務器

2022-11-08 11:26:13

Go逃逸代碼

2021-09-16 07:52:18

算法應用場景

2021-11-09 14:08:45

DockerDockerfileJava

2019-05-10 10:50:04

Spring AOPJDK動態代理CGLIB動態代理

2021-05-28 11:18:50

MySQLbin logredo log

2021-11-05 07:47:56

代理模式對象

2021-11-09 08:51:13

模式命令面試

2021-11-10 07:47:49

組合模式場景

2021-11-02 22:04:58

模式

2021-08-16 08:33:26

git

2021-11-03 14:10:28

工廠模式場景

2021-09-26 10:57:16

集合操作場景

2021-09-27 06:50:04

非線性數據

2021-09-28 07:12:09

測試路徑

2021-11-11 16:37:05

模板模式方法
點贊
收藏

51CTO技術棧公眾號

久久99深爱久久99精品| 日韩超碰人人爽人人做人人添| 日本一区二区视频在线| 国产在线视频一区| 九九视频免费在线观看| 加勒比久久高清| 欧美写真视频网站| 99久久99久久精品| 青青草av免费在线观看| 久88久久88久久久| 久久久久九九九九| 免费黄在线观看| 96sao在线精品免费视频| 欧美视频在线免费| 在线观看污视频| 黄色大片在线看| 国产成人精品在线看| 国产精品久久久久免费a∨| 欧美黄色免费在线观看| 精品99久久| 精品久久国产老人久久综合| 超碰在线播放91| 少妇视频一区| 一区二区三区在线影院| 视频一区视频二区视频三区高| 成人1区2区3区| 精品一区二区三区不卡| 日韩美女在线观看一区| 国产主播在线观看| 91精品秘密在线观看| 亚洲欧美日韩国产中文专区| 国产视频精品视频| 国产视频网站一区二区三区| 91黄色小视频| 亚洲中文字幕无码中文字| 最新国产在线拍揄自揄视频| 国产精品视频在线看| 久久久com| 亚洲产国偷v产偷v自拍涩爱| 久久99久久99精品免视看婷婷| 青草热久免费精品视频| 国产在线视频二区| 一区二区蜜桃| 日韩在线国产精品| 夜夜春很很躁夜夜躁| 九色精品国产蝌蚪| 日韩电视剧免费观看网站| 影音先锋资源av| 久久综合偷偷噜噜噜色| 欧美欧美欧美欧美| 99热这里只有精品在线播放| 3d欧美精品动漫xxxx无尽| 精品毛片网大全| 国产综合中文字幕| h片在线观看视频免费免费| 依依成人综合视频| 男人添女人下部视频免费| 成人看av片| 一区二区三区在线视频播放| 久久久久久久免费视频| www免费视频观看在线| 亚洲精品视频在线看| 91国在线高清视频| 国产丝袜精品丝袜| 午夜影院久久久| 大陆极品少妇内射aaaaa| yellow在线观看网址| 午夜精品aaa| www黄色av| 成人软件在线观看| 欧美日韩和欧美的一区二区| 午夜啪啪小视频| 视频一区视频二区欧美| 精品久久久久一区二区国产| 亚洲制服丝袜在线播放| 国产一区二区观看| 日韩视频免费大全中文字幕| 久草视频手机在线观看| 国产精品久久久久毛片大屁完整版 | 污视频网站观看| 四虎影视成人精品国库在线观看| 91精品国产综合久久精品图片| 中文字幕55页| 欧美18免费视频| 亚洲深夜福利网站| 国产免费一区二区三区四区| 午夜日韩视频| 日本一区二区在线免费播放| 一级特黄aa大片| 成人午夜大片免费观看| 日本不卡免费新一二三区| av网页在线| 亚洲五月六月丁香激情| 日本一本二本在线观看| 日韩福利在线观看| 精品国内片67194| 国产亚洲精品熟女国产成人| 亚洲九九在线| 欧美有码在线观看视频| 国产剧情久久久| 91欧美一区二区| 波多野结衣三级在线| 日韩深夜视频| 6080国产精品一区二区| 性色av蜜臀av色欲av| 欧美电影三区| 欧美一级片在线播放| 国产免费高清av| 久久免费国产精品| 欧美 国产 精品| 成人在线视频播放| 亚洲国产成人在线播放| 四虎永久免费地址| 久久久久国产精品一区三寸| 97超碰人人模人人爽人人看| 黄色av网站在线免费观看| 亚洲国产精品久久人人爱| 孩娇小videos精品| 亚洲天堂日韩在线| 欧美精品电影免费在线观看| 亚洲一区二区视频在线播放| 91麻豆产精品久久久久久| 米仓穗香在线观看| 久久女人天堂| 亚洲香蕉在线观看| 少妇一级淫片免费放中国| 国产福利一区在线观看| 亚洲人成网站在线播放2019| 樱花草涩涩www在线播放| 日韩亚洲国产中文字幕欧美| 蜜桃av免费观看| 天堂av在线一区| 精品人伦一区二区三区| 欧美人体视频xxxxx| 欧美日韩第一区日日骚| 国产综合精品久久久久成人av| 99亚洲视频| 国产精品18毛片一区二区| 成人在线播放免费观看| 欧美天堂亚洲电影院在线播放 | 国产精品国产a级| 麻豆传传媒久久久爱| 亚洲精品中文字幕99999| 97视频在线观看亚洲| 亚洲精品国偷拍自产在线观看蜜桃| 一区免费观看视频| 亚洲视频一二三四| 91久久夜色精品国产按摩| 国产精品视频一区国模私拍| 国产高清一级毛片在线不卡| 91国产精品成人| 国产亚洲精品熟女国产成人| 日韩vs国产vs欧美| 天堂资源在线亚洲资源| 欧美va在线| 国产一区二区三区三区在线观看| 国产精品乱码一区二区视频| 国产欧美日韩视频一区二区| 男操女免费网站| 日韩三级在线| 亚洲一区亚洲二区亚洲三区| 四季久久免费一区二区三区四区| 精品福利在线导航| 中国一级特黄毛片| 久久午夜免费电影| 成年人在线观看视频免费| 清纯唯美亚洲综合一区| 成人黄在线观看| 中文在线免费| 亚洲国产高清高潮精品美女| 久久精品国产成人av| 久久综合国产精品| 黑人粗进入欧美aaaaa| 久久精品国产99久久| 91夜夜未满十八勿入爽爽影院| 欧美黄色视屏| 亚洲精品有码在线| 中文字幕制服诱惑| 亚洲午夜在线观看视频在线| av无码av天天av天天爽| 日本午夜一区二区| 午夜久久久久久久久久久| 蜜臀av一区| 国产欧美日韩综合精品| 手机在线免费观看av| 国产视频精品xxxx| 一级特黄aaa大片| 亚洲成人av电影| 先锋影音av在线| 国产成人av一区二区三区在线观看| 激情伊人五月天| 日韩免费高清| 国产精品.com| 久久99国产精品二区高清软件| 欧美日韩国产第一页| 噜噜噜噜噜在线视频| 欧美一区二区精美| 国产高潮久久久| 亚洲乱码国产乱码精品精的特点| 欧美深性狂猛ⅹxxx深喉| 毛片av一区二区| 美女日批免费视频| 天天射成人网| 欧美日韩综合久久| 中文字幕区一区二区三| 国产精品丝袜一区二区三区| 国产拍在线视频| 久久久国产视频91| 毛片在线能看| 精品嫩草影院久久| 一卡二卡三卡在线观看| 欧美日韩中文字幕综合视频| 国产大学生自拍| 欧美国产日韩亚洲一区| 午夜视频在线观看国产| 九色|91porny| 污污视频网站免费观看| 伊人久久大香线蕉av超碰演员| 一区二区三区国| 国内精品久久久久久久久电影网| 99re国产| 精品网站999| 国产精品视频专区| 偷拍视频一区二区三区| 午夜精品久久久久久久久久久久 | 欧美在线视频观看免费网站| 国产精品一卡二卡三卡| 一区二区三区精品99久久| 天天操天天干天天插| 日韩欧美一区二区不卡| 一级黄色免费片| 欧洲精品一区二区三区在线观看| 欧美a∨亚洲欧美亚洲| 亚洲综合色网站| 欧美三级黄色大片| 国产精品伦一区| 免费黄色在线网址| 亚洲国产高清aⅴ视频| 免费看黄色aaaaaa 片| 99国产精品久| 制服丝袜第一页在线观看| 国产成人av自拍| 男人女人拔萝卜视频| 日韩不卡一区二区三区 | 国产福利久久久| 一区二区三区在线影院| 日韩欧美综合视频| 亚洲欧美另类小说| 一起操在线播放| 亚洲精品中文字幕乱码三区| 欧美卡一卡二卡三| 亚洲一区二区三区视频在线播放| 清纯粉嫩极品夜夜嗨av| 亚洲午夜精品网| 日本少妇性高潮| 欧美日韩在线免费观看| 男人天堂av在线播放| 欧美性色黄大片手机版| 中文字幕在线观看1| 777亚洲妇女| 精品人妻伦一二三区久久| 精品免费国产一区二区三区四区| 欧性猛交ⅹxxx乱大交| 日韩精品欧美激情| 国产在线观看免费| 日韩中文娱乐网| 中文字幕资源网在线观看| 欧美国产精品人人做人人爱 | 国产精品久久一| 色综合视频一区二区三区44| 91亚洲永久免费精品| 成人在线超碰| 欧美一卡2卡3卡4卡无卡免费观看水多多| 国产伦精品一区二区三区千人斩| 夜夜爽99久久国产综合精品女不卡| 婷婷亚洲五月| 亚洲国产精品无码av| 久久久久久久高潮| 爱爱爱爱免费视频| 大胆亚洲人体视频| 亚洲熟妇一区二区三区| 国产精品免费视频网站| 精品99久久久久成人网站免费 | 岳毛多又紧做起爽| 久久精品国内一区二区三区| 国产老头和老头xxxx×| 91捆绑美女网站| 夫妻性生活毛片| 狠狠躁夜夜躁久久躁别揉| 中文字幕视频在线播放| 精品日韩99亚洲| 成年午夜在线| 欧美激情中文字幕乱码免费| 456亚洲精品成人影院| 91免费在线观看网站| 国产成人短视频在线观看| 青草全福视在线| 久久性天堂网| 无码人妻一区二区三区免费n鬼沢| 久久久久成人黄色影片| 久久机热这里只有精品| 欧美午夜不卡在线观看免费| 蜜臀久久久久久999| 日韩一区二区精品视频| 神马久久午夜| 97se在线视频| 久久一本综合| 免费观看日韩毛片| 国产风韵犹存在线视精品| 欧美乱大交做爰xxxⅹ小说| 亚洲成年人影院| 一级特黄色大片| 国产亚洲日本欧美韩国| 制服丝袜专区在线| 成人免费视频视频在| 手机在线一区二区三区| 久久精品.com| 99在线热播精品免费| 欧美另类视频在线观看| 欧美人伦禁忌dvd放荡欲情| 免费成人av电影| 77777少妇光屁股久久一区| 天堂va欧美ⅴa亚洲va一国产| 一区二区三区四区国产| 肉色丝袜一区二区| 亚洲国产综合视频| 亚洲v日本v欧美v久久精品| 精品国产九九九| 久久精品国产精品| 日本在线中文字幕一区二区三区| 久久免费一区| 宅男噜噜噜66一区二区| 国产一卡二卡三卡四卡| 亚洲精品国产一区二区精华液| 一区二区视频网站| 中文在线资源观看视频网站免费不卡| 欧美电影免费观看高清完整| 欧美lavv| 首页亚洲欧美制服丝腿| 在线观看福利片| 日本精品一级二级| 毛片免费在线播放| 日韩免费观看高清| 精品久久久久久久| 在线观看av日韩| 欧美国产日本视频| 亚洲午夜精品久久久| 少妇精69xxtheporn| 欧美日韩卡一| 中文字幕中文字幕在线中心一区| 麻豆国产欧美一区二区三区| 青青青视频在线播放| 欧美精品在线观看播放| 黄色大片在线播放| 亚洲一区二区少妇| 欧美一区二区三区另类| 绯色av蜜臀vs少妇| 亚洲成年人影院| 你懂的在线免费观看| 国产精品亚洲美女av网站| 婷婷亚洲五月色综合| 免费国偷自产拍精品视频| 亚洲在线视频网站| 色wwwwww| 国产精品久久中文| 91精品福利| 亚洲天堂av网站| 一道本成人在线| 欧美13一16娇小xxxx| 亚洲a中文字幕| 一区二区黄色| 一本在线免费视频| 欧美变态tickle挠乳网站| 亚洲美女尤物影院| 亚洲精品一区二区三区樱花| 国产一二精品视频| 国产成人无码精品久在线观看| 亚洲色图15p| 久久99成人| 男人天堂999| 综合久久久久综合| 色婷婷av一区二区三区之e本道| 国产成人精品av在线| 亚洲自拍偷拍网| 国产福利短视频| 91精品国产综合久久香蕉的特点| h片精品在线观看| 日韩欧美亚洲区| 成人一道本在线| 日韩欧美一级大片| 欧美激情亚洲一区| 俺要去色综合狠狠| 中文字幕乱视频| 777久久久精品| 在线观看涩涩| 91国在线高清视频| 中文字幕久久午夜不卡| 四虎精品一区二区三区| 国产日本欧美在线观看| 亚洲综合国产|