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

服務(wù)器之家:專注于服務(wù)器技術(shù)及軟件下載分享
分類導(dǎo)航

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

服務(wù)器之家 - 編程語言 - JAVA教程 - Java中的異常處理用法及其架構(gòu)和使用建議

Java中的異常處理用法及其架構(gòu)和使用建議

2020-05-13 14:15skywangkw JAVA教程

Java同樣也提供了拋出異常、捕捉異常和finally語句的使用來處理程序異常,下面就來具體看一下Java中的異常處理用法及其架構(gòu)和使用建議:

Java異常是Java提供的一種識別及響應(yīng)錯(cuò)誤的一致性機(jī)制。
Java異常機(jī)制可以使程序中異常處理代碼和正常業(yè)務(wù)代碼分離,保證程序代碼更加優(yōu)雅,并提高程序健壯性。在有效使用異常的情況下,異常能清晰的回答what, where, why這3個(gè)問題:異常類型回答了“什么”被拋出,異常堆棧跟蹤回答了“在哪“拋出,異常信息回答了“為什么“會拋出。
Java異常機(jī)制用到的幾個(gè)關(guān)鍵字:try、catch、finally、throw、throws。

關(guān)鍵字

說明

try

用于監(jiān)聽。將要被監(jiān)聽的代碼(可能拋出異常的代碼)放在try語句塊之內(nèi),當(dāng)try語句塊內(nèi)發(fā)生異常時(shí),異常就被拋出。

catch

用于捕獲異常。catch用來捕獲try語句塊中發(fā)生的異常。

finally

finally語句塊總是會被執(zhí)行。它主要用于回收在try塊里打開的物力資源(如數(shù)據(jù)庫連接、網(wǎng)絡(luò)連接和磁盤文件)。只有finally塊,執(zhí)行完成之后,才會回來執(zhí)行try或者catch塊中的return或者throw語句,如果finally中使用了return或者throw等終止方法的語句,則就不會跳回執(zhí)行,直接停止。

throw

用于拋出異常。

throws

用在方法簽名中,用于聲明該方法可能拋出的異常。


下面通過幾個(gè)示例對這幾個(gè)關(guān)鍵字進(jìn)行簡單了解。
示例一: 了解try和catch基本用法

 

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class Demo1 {
 
 public static void main(String[] args) {
  try {
   int i = 10/0;
    System.out.println("i="+i);
  } catch (ArithmeticException e) {
    System.out.println("Caught Exception");
   System.out.println("e.getMessage(): " + e.getMessage());
   System.out.println("e.toString(): " + e.toString());
   System.out.println("e.printStackTrace():");
   e.printStackTrace();
  }
 }
}

運(yùn)行結(jié)果:

?
1
2
3
4
5
6
Caught Exception
e.getMessage(): / by zero
e.toString(): java.lang.ArithmeticException: / by zero
e.printStackTrace():
java.lang.ArithmeticException: / by zero
 at Demo1.main(Demo1.java:6)

結(jié)果說明:在try語句塊中有除數(shù)為0的操作,該操作會拋出java.lang.ArithmeticException異常。通過catch,對該異常進(jìn)行捕獲。
觀察結(jié)果我們發(fā)現(xiàn),并沒有執(zhí)行System.out.println("i="+i)。這說明try語句塊發(fā)生異常之后,try語句塊中的剩余內(nèi)容就不會再被執(zhí)行了。
示例二: 了解finally的基本用法
在"示例一"的基礎(chǔ)上,我們添加finally語句。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class Demo2 {
 
 public static void main(String[] args) {
  try {
   int i = 10/0;
    System.out.println("i="+i);
  } catch (ArithmeticException e) {
    System.out.println("Caught Exception");
   System.out.println("e.getMessage(): " + e.getMessage());
   System.out.println("e.toString(): " + e.toString());
   System.out.println("e.printStackTrace():");
   e.printStackTrace();
  } finally {
   System.out.println("run finally");
  }
 }
}

運(yùn)行結(jié)果:

?
1
2
3
4
5
6
7
Caught Exception
e.getMessage(): / by zero
e.toString(): java.lang.ArithmeticException: / by zero
e.printStackTrace():
java.lang.ArithmeticException: / by zero
 at Demo2.main(Demo2.java:6)
run finally

結(jié)果說明:最終執(zhí)行了finally語句塊。
示例三: 了解throws和throw的基本用法
throws是用于聲明拋出的異常,而throw是用于拋出異常。

?
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
class MyException extends Exception {
 public MyException() {}
 public MyException(String msg) {
  super(msg);
 }
}
 
public class Demo3 {
 
 public static void main(String[] args) {
  try {
   test();
  } catch (MyException e) {
   System.out.println("Catch My Exception");
   e.printStackTrace();
  }
 }
 public static void test() throws MyException{
  try {
   int i = 10/0;
    System.out.println("i="+i);
  } catch (ArithmeticException e) {
   throw new MyException("This is MyException");
  }
 }
}

運(yùn)行結(jié)果:

?
1
2
3
4
Catch My Exception
MyException: This is MyException
 at Demo3.test(Demo3.java:24)
 at Demo3.main(Demo3.java:13)

結(jié)果說明:MyException是繼承于Exception的子類。test()的try語句塊中產(chǎn)生ArithmeticException異常(除數(shù)為0),并在catch中捕獲該異常;接著拋出MyException異常。main()方法對test()中拋出的MyException進(jìn)行捕獲處理。


Java異常框架
Java異常架構(gòu)圖:
Java中的異常處理用法及其架構(gòu)和使用建議

1. Throwable
Throwable是 Java 語言中所有錯(cuò)誤或異常的超類。
Throwable包含兩個(gè)子類: Error 和 Exception。它們通常用于指示發(fā)生了異常情況。
Throwable包含了其線程創(chuàng)建時(shí)線程執(zhí)行堆棧的快照,它提供了printStackTrace()等接口用于獲取堆棧跟蹤數(shù)據(jù)等信息。

2. Exception
Exception及其子類是 Throwable 的一種形式,它指出了合理的應(yīng)用程序想要捕獲的條件。

3. RuntimeException
RuntimeException是那些可能在 Java 虛擬機(jī)正常運(yùn)行期間拋出的異常的超類。
編譯器不會檢查RuntimeException異常。例如,除數(shù)為零時(shí),拋出ArithmeticException異常。RuntimeException是ArithmeticException的超類。當(dāng)代碼發(fā)生除數(shù)為零的情況時(shí),倘若既"沒有通過throws聲明拋出ArithmeticException異常",也"沒有通過try...catch...處理該異常",也能通過編譯。這就是我們所說的"編譯器不會檢查RuntimeException異常"!
如果代碼會產(chǎn)生RuntimeException異常,則需要通過修改代碼進(jìn)行避免。例如,若會發(fā)生除數(shù)為零的情況,則需要通過代碼避免該情況的發(fā)生!

4. Error
和Exception一樣,Error也是Throwable的子類。它用于指示合理的應(yīng)用程序不應(yīng)該試圖捕獲的嚴(yán)重問題,大多數(shù)這樣的錯(cuò)誤都是異常條件。
和RuntimeException一樣,編譯器也不會檢查Error。
Java將可拋出(Throwable)的結(jié)構(gòu)分為三種類型:被檢查的異常(Checked Exception),運(yùn)行時(shí)異常(RuntimeException)和錯(cuò)誤(Error)。

(1) 運(yùn)行時(shí)異常
定義: RuntimeException及其子類都被稱為運(yùn)行時(shí)異常。
特點(diǎn): Java編譯器不會檢查它。也就是說,當(dāng)程序中可能出現(xiàn)這類異常時(shí),倘若既"沒有通過throws聲明拋出它",也"沒有用try-catch語句捕獲它",還是會編譯通過。例如,除數(shù)為零時(shí)產(chǎn)生的ArithmeticException異常,數(shù)組越界時(shí)產(chǎn)生的IndexOutOfBoundsException異常,fail-fail機(jī)制產(chǎn)生的ConcurrentModificationException異常等,都屬于運(yùn)行時(shí)異常。
     雖然Java編譯器不會檢查運(yùn)行時(shí)異常,但是我們也可以通過throws進(jìn)行聲明拋出,也可以通過try-catch對它進(jìn)行捕獲處理。
     如果產(chǎn)生運(yùn)行時(shí)異常,則需要通過修改代碼來進(jìn)行避免。例如,若會發(fā)生除數(shù)為零的情況,則需要通過代碼避免該情況的發(fā)生!

(2) 被檢查的異常
定義: Exception類本身,以及Exception的子類中除了"運(yùn)行時(shí)異常"之外的其它子類都屬于被檢查異常。
特點(diǎn): Java編譯器會檢查它。此類異常,要么通過throws進(jìn)行聲明拋出,要么通過try-catch進(jìn)行捕獲處理,否則不能通過編譯。例如,CloneNotSupportedException就屬于被檢查異常。當(dāng)通過clone()接口去克隆一個(gè)對象,而該對象對應(yīng)的類沒有實(shí)現(xiàn)Cloneable接口,就會拋出CloneNotSupportedException異常。
     被檢查異常通常都是可以恢復(fù)的。

(3) 錯(cuò)誤
定義: Error類及其子類。
特點(diǎn): 和運(yùn)行時(shí)異常一樣,編譯器也不會對錯(cuò)誤進(jìn)行檢查。
     當(dāng)資源不足、約束失敗、或是其它程序無法繼續(xù)運(yùn)行的條件發(fā)生時(shí),就產(chǎn)生錯(cuò)誤。程序本身無法修復(fù)這些錯(cuò)誤的。例如,VirtualMachineError就屬于錯(cuò)誤。
     按照J(rèn)ava慣例,我們是不應(yīng)該是實(shí)現(xiàn)任何新的Error子類的!
對于上面的3種結(jié)構(gòu),我們在拋出異常或錯(cuò)誤時(shí),到底該哪一種?《Effective Java》中給出的建議是:對于可以恢復(fù)的條件使用被檢查異常,對于程序錯(cuò)誤使用運(yùn)行時(shí)異常。

關(guān)于異常處理的幾條建議

第1條: 只針對不正常的情況才使用異常
建議:異常只應(yīng)該被用于不正常的條件,它們永遠(yuǎn)不應(yīng)該被用于正常的控制流。
通過比較下面的兩份代碼進(jìn)行說明。
代碼1

?
1
2
3
4
5
6
7
8
9
10
11
12
try {
 int i=0;
 while (true) {
  arr[i]=0;
  i++;
 }
} catch (IndexOutOfBoundsException e) {
}
代碼2
for (int i=0; i<arr.length; i++) {
 arr[i]=0;
}

兩份代碼的作用都是遍歷arr數(shù)組,并設(shè)置數(shù)組中每一個(gè)元素的值為0。代碼1的是通過異常來終止,看起來非常難懂,代碼2是通過數(shù)組邊界來終止。我們應(yīng)該避免使用代碼1這種方式,主要原因有三點(diǎn):
異常機(jī)制的設(shè)計(jì)初衷是用于不正常的情況,所以很少會會JVM實(shí)現(xiàn)試圖對它們的性能進(jìn)行優(yōu)化。所以,創(chuàng)建、拋出和捕獲異常的開銷是很昂貴的。
把代碼放在try-catch中返回阻止了JVM實(shí)現(xiàn)本來可能要執(zhí)行的某些特定的優(yōu)化。
對數(shù)組進(jìn)行遍歷的標(biāo)準(zhǔn)模式并不會導(dǎo)致冗余的檢查,有些現(xiàn)代的JVM實(shí)現(xiàn)會將它們優(yōu)化掉。
實(shí)際上,基于異常的模式比標(biāo)準(zhǔn)模式要慢得多。測試代碼如下:

?
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
public class Advice1 {
 
 private static int[] arr = new int[]{1,2,3,4,5};
 private static int SIZE = 10000;
 
 public static void main(String[] args) {
 
  long s1 = System.currentTimeMillis();
  for (int i=0; i<SIZE; i++)
   endByRange(arr);
  long e1 = System.currentTimeMillis();
  System.out.println("endByRange time:"+(e1-s1)+"ms" );
 
  long s2 = System.currentTimeMillis();
  for (int i=0; i<SIZE; i++)
   endByException(arr);
  long e2 = System.currentTimeMillis();
  System.out.println("endByException time:"+(e2-s2)+"ms" );
 }
 
 // 遍歷arr數(shù)組: 通過異常的方式
 private static void endByException(int[] arr) {
  try {
   int i=0;
   while (true) {
    arr[i]=0;
    i++;
    //System.out.println("endByRange: arr["+i+"]="+arr[i]);
   }
  } catch (IndexOutOfBoundsException e) {
  }
 }
 
 // 遍歷arr數(shù)組: 通過邊界的方式
 private static void endByRange(int[] arr) {
  for (int i=0; i<arr.length; i++) {
   arr[i]=0;
   //System.out.println("endByException: arr["+i+"]="+arr[i]);
  }
 }
}

運(yùn)行結(jié)果:

?
1
2
endByRange time:8ms
endByException time:16ms

結(jié)果說明:通過異常遍歷的速度比普通方式遍歷數(shù)組慢很多!

第2條: 對于可恢復(fù)的條件使用被檢查的異常,對于程序錯(cuò)誤使用運(yùn)行時(shí)異常

異常

說明

運(yùn)行時(shí)異常

RuntimeException類及其子類都被稱為運(yùn)行時(shí)異常。

被檢查的異常

Exception類本身,以及Exception的子類中除了"運(yùn)行時(shí)異常"之外的其它子類都屬于被檢查異常

 

 

它們的區(qū)別是:Java編譯器會對"被檢查的異常"進(jìn)行檢查,而對"運(yùn)行時(shí)異常"不會檢查。
也就是說,對于被檢查的異常,要么通過throws進(jìn)行聲明拋出,要么通過try-catch進(jìn)行捕獲處理,否則不能通過編譯。而對于運(yùn)行時(shí)異常,倘若既"沒有通過throws聲明拋出它",也"沒有用try-catch語句捕獲它",還是會編譯通過。當(dāng)然,雖說Java編譯器不會檢查運(yùn)行時(shí)異常,但是,我們同樣可以通過throws對該異常進(jìn)行說明,或通過try-catch進(jìn)行捕獲。
rithmeticException(例如,除數(shù)為0),IndexOutOfBoundsException(例如,數(shù)組越界)等都屬于運(yùn)行時(shí)異常。對于這種異常,我們應(yīng)該通過修改代碼進(jìn)行避免它的產(chǎn)生。而對于被檢查的異常,則可以通過處理讓程序恢復(fù)運(yùn)行。例如,假設(shè)因?yàn)橐粋€(gè)用戶沒有存儲足夠數(shù)量的前,所以他在企圖在一個(gè)收費(fèi)電話上進(jìn)行呼叫就會失敗;于是就將一個(gè)被檢查異常拋出。

第3條: 避免不必要的使用被檢查的異常
"被檢查的異常"是Java語言的一個(gè)很好的特性。與返回代碼不同,"被檢查的異常"會強(qiáng)迫程序員處理例外的條件,大大提高了程序的可靠性。
但是,過分使用被檢查異常會使API用起來非常不方便。如果一個(gè)方法拋出一個(gè)或多個(gè)被檢查的異常,那么調(diào)用該方法的代碼則必須在一個(gè)或多個(gè)catch語句塊中處理這些異常,或者必須通過throws聲明拋出這些異常。 無論是通過catch處理,還是通過throws聲明拋出,都給程序員添加了不可忽略的負(fù)擔(dān)。
適用于"被檢查的異常"必須同時(shí)滿足兩個(gè)條件:第一,即使正確使用API并不能阻止異常條件的發(fā)生。第二,一旦產(chǎn)生了異常,使用API的程序員可以采取有用的動作對程序進(jìn)行處理。

第4條: 盡量使用標(biāo)準(zhǔn)的異常
代碼重用是值得提倡的,這是一條通用規(guī)則,異常也不例外。重用現(xiàn)有的異常有幾個(gè)好處:
第一,它使得你的API更加易于學(xué)習(xí)和使用,因?yàn)樗c程序員原來已經(jīng)熟悉的習(xí)慣用法是一致的。
第二,對于用到這些API的程序而言,它們的可讀性更好,因?yàn)樗鼈儾粫涑庵绦騿T不熟悉的異常。
第三,異常類越少,意味著內(nèi)存占用越小,并且轉(zhuǎn)載這些類的時(shí)間開銷也越小。
Java標(biāo)準(zhǔn)異常中有幾個(gè)是經(jīng)常被使用的異常。如下表格:

異常

使用場合

IllegalArgumentException

參數(shù)的值不合適

IllegalStateException

參數(shù)的狀態(tài)不合適

NullPointerException

在null被禁止的情況下參數(shù)值為null

IndexOutOfBoundsException

下標(biāo)越界

ConcurrentModificationException

在禁止并發(fā)修改的情況下,對象檢測到并發(fā)修改

UnsupportedOperationException

對象不支持客戶請求的方法

 

雖然它們是Java平臺庫迄今為止最常被重用的異常,但是,在許可的條件下,其它的異常也可以被重用。例如,如果你要實(shí)現(xiàn)諸如復(fù)數(shù)或者矩陣之類的算術(shù)對象,那么重用ArithmeticException和NumberFormatException將是非常合適的。如果一個(gè)異常滿足你的需要,則不要猶豫,使用就可以,不過你一定要確保拋出異常的條件與該異常的文檔中描述的條件一致。這種重用必須建立在語義的基礎(chǔ)上,而不是名字的基礎(chǔ)上!
最后,一定要清楚,選擇重用哪一種異常并沒有必須遵循的規(guī)則。例如,考慮紙牌對象的情形,假設(shè)有一個(gè)用于發(fā)牌操作的方法,它的參數(shù)(handSize)是發(fā)一手牌的紙牌張數(shù)。假設(shè)調(diào)用者在這個(gè)參數(shù)中傳遞的值大于整副牌的剩余張數(shù)。那么這種情形既可以被解釋為IllegalArgumentException(handSize的值太大),也可以被解釋為IllegalStateException(相對客戶的請求而言,紙牌對象的紙牌太少)。

第5條: 拋出的異常要適合于相應(yīng)的抽象
如果一個(gè)方法拋出的異常與它執(zhí)行的任務(wù)沒有明顯的關(guān)聯(lián)關(guān)系,這種情形會讓人不知所措。當(dāng)一個(gè)方法傳遞一個(gè)由低層抽象拋出的異常時(shí),往往會發(fā)生這種情況。這種情況發(fā)生時(shí),不僅讓人困惑,而且也"污染"了高層API。
為了避免這個(gè)問題,高層實(shí)現(xiàn)應(yīng)該捕獲低層的異常,同時(shí)拋出一個(gè)可以按照高層抽象進(jìn)行介紹的異常。這種做法被稱為"異常轉(zhuǎn)譯(exception translation)"。
例如,在Java的集合框架AbstractSequentialList的get()方法如下(基于JDK1.7.0_40):

?
1
2
3
4
5
6
7
public E get(int index) {
 try {
  return listIterator(index).next();
 } catch (NoSuchElementException exc) {
  throw new IndexOutOfBoundsException("Index: "+index);
 }
}

listIterator(index)會返回ListIterator對象,調(diào)用該對象的next()方法可能會拋出NoSuchElementException異常。而在get()方法中,拋出NoSuchElementException異常會讓人感到困惑。所以,get()對NoSuchElementException進(jìn)行了捕獲,并拋出了IndexOutOfBoundsException異常。即,相當(dāng)于將NoSuchElementException轉(zhuǎn)譯成了IndexOutOfBoundsException異常。

第6條: 每個(gè)方法拋出的異常都要有文檔
要單獨(dú)的聲明被檢查的異常,并且利用Javadoc的@throws標(biāo)記,準(zhǔn)確地記錄下每個(gè)異常被拋出的條件。
如果一個(gè)類中的許多方法處于同樣的原因而拋出同一個(gè)異常,那么在該類的文檔注釋中對這個(gè)異常做文檔,而不是為每個(gè)方法單獨(dú)做文檔,這是可以接受的。

第7條: 在細(xì)節(jié)消息中包含失敗 -- 捕獲消息
簡而言之,當(dāng)我們自定義異常或者拋出異常時(shí),應(yīng)該包含失敗相關(guān)的信息。
當(dāng)一個(gè)程序由于一個(gè)未被捕獲的異常而失敗的時(shí)候,系統(tǒng)會自動打印出該異常的棧軌跡。在棧軌跡中包含該異常的字符串表示。典型情況下它包含該異常類的類名,以及緊隨其后的細(xì)節(jié)消息。

第8條: 努力使失敗保持原子性
當(dāng)一個(gè)對象拋出一個(gè)異常之后,我們總期望這個(gè)對象仍然保持在一種定義良好的可用狀態(tài)之中。對于被檢查的異常而言,這尤為重要,因?yàn)檎{(diào)用者通常期望從被檢查的異常中恢復(fù)過來。
一般而言,一個(gè)失敗的方法調(diào)用應(yīng)該保持使對象保持在"它在被調(diào)用之前的狀態(tài)"。具有這種屬性的方法被稱為具有"失敗原子性(failure atomic)"。可以理解為,失敗了還保持著原子性。對象保持"失敗原子性"的方式有幾種:
(1) 設(shè)計(jì)一個(gè)非可變對象。
(2) 對于在可變對象上執(zhí)行操作的方法,獲得"失敗原子性"的最常見方法是,在執(zhí)行操作之前檢查參數(shù)的有效性。如下(Stack.java中的pop方法):

?
1
2
3
4
5
6
7
public Object pop() {
 if (size==0)
  throw new EmptyStackException();
 Object result = elements[--size];
 elements[size] = null;
 return result;
}

(3) 與上一種方法類似,可以對計(jì)算處理過程調(diào)整順序,使得任何可能會失敗的計(jì)算部分都發(fā)生在對象狀態(tài)被修改之前。
(4) 編寫一段恢復(fù)代碼,由它來解釋操作過程中發(fā)生的失敗,以及使對象回滾到操作開始之前的狀態(tài)上。
(5) 在對象的一份臨時(shí)拷貝上執(zhí)行操作,當(dāng)操作完成之后再把臨時(shí)拷貝中的結(jié)果復(fù)制給原來的對象。
雖然"保持對象的失敗原子性"是期望目標(biāo),但它并不總是可以做得到。例如,如果多個(gè)線程企圖在沒有適當(dāng)?shù)耐綑C(jī)制的情況下,并發(fā)的訪問一個(gè)對象,那么該對象就有可能被留在不一致的狀態(tài)中。
即使在可以實(shí)現(xiàn)"失敗原子性"的場合,它也不是總被期望的。對于某些操作,它會顯著的增加開銷或者復(fù)雜性。
總的規(guī)則是:作為方法規(guī)范的一部分,任何一個(gè)異常都不應(yīng)該改變對象調(diào)用該方法之前的狀態(tài),如果這條規(guī)則被違反,則API文檔中應(yīng)該清楚的指明對象將會處于什么樣的狀態(tài)。

第9條: 不要忽略異常
當(dāng)一個(gè)API的設(shè)計(jì)者聲明一個(gè)方法會拋出某個(gè)異常的時(shí)候,他們正在試圖說明某些事情。所以,請不要忽略它!忽略異常的代碼如下:

?
1
2
3
4
try {
 ...
} catch (SomeException e) {
}

空的catch塊會使異常達(dá)不到應(yīng)有的目的,異常的目的是強(qiáng)迫你處理不正常的條件。忽略一個(gè)異常,就如同忽略一個(gè)火警信號一樣 -- 若把火警信號器關(guān)閉了,那么當(dāng)真正的火災(zāi)發(fā)生時(shí),就沒有人看到火警信號了。所以,至少catch塊應(yīng)該包含一條說明,用來解釋為什么忽略這個(gè)異常是合適的。

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 国产精品免费看香蕉 | 亚洲国产精品日韩高清秒播 | 国产二区视频在线观看 | 欧美日本一道高清二区三区 | 国产精品青青青高清在线密亚 | 美女张开大腿让男人桶 | 精品一区二区三区高清免费观看 | 久久青草费线频观看国产 | 欧美亚洲欧美 | 超级碰在线视频 | 欧美一区二区三区在线观看不卡 | 免费高清视频日本 | 日韩色图区 | 亚洲欧美日韩精品久久亚洲区 | 国产成人久久 | 欧美怡红院视频一区二区三区 | 日韩在线观看免费 | 大胸被c出奶水嗷嗷叫 | 亚洲一区二区精品视频 | 草莓茄子丝瓜番茄小蝌蚪 | 午夜视频一区二区 | 亚洲国产精品一区二区首页 | 国内精品国语自产拍在线观看55 | 国内会所按摩推拿国产 | 色综合色狠狠天天久久婷婷基地 | a人片| 外女思春台湾三级 | 俄罗斯一级淫片bbbb | 男女交性特一级 | 成人欧美一区二区三区黑人 | 国产精品第一 | 好硬好大好浪夹得好紧h | 范冰冰性xxxxhd | 久青草国产观看在线视频 | 色老板在线观看 | 91传媒制片厂制作传媒破解版 | 艾秋麻豆果冻剧传媒在线播放 | 青青网在线视频 | 啊啊啊好大视频 | 国产午夜精品理论片 | 男生和老师一起差差差 |