日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

JAVA泛型知识(一)

發布時間:2024/8/26 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 JAVA泛型知识(一) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Java泛型知識(二)<? extends T>和<? super T>

?

Java1.5泛型指南中文版(Java1.5 Generic Tutorial)

?

目????????錄

?

摘要和關鍵字

1.???????介紹

2.???????定義簡單的泛型

3.???????泛型和子類繼承

4.???????通配符(Wildcards)

4.1.???????有限制的通配符(Bounded Wildcards)

5.???????泛型方法

6.???????與舊代碼交互

6.1.???????在泛型代碼中使用老代碼

6.2.???????擦除和翻譯(Erasure and Translation)

6.3.?????在老代碼中使用泛型代碼

7.???????要點(The Fine Print)

7.1.???????一個泛型類被其所有調用共享

7.2.???????轉型和instanceof

7.3.???????數組Arrays

8.???????Class Literals as Run-time Type Tokens

9.???????More fun with *

9.1.???????通配符匹配(wildcard capture)

10.?????泛型化老代碼

11.?????致謝

?

摘要和關鍵字

???????generics、type safe、type parameter(variable)、formal type parameter、actual type parameter、wildcards(?)、unknown type、? extends T、? super T、erasure、translation、cast、instanceof、arrays、Class Literals as Run-time Type Tokens、wildcard capture、multiple bounds(T extends T1& T2 ... & Tn)、covariant returns

?

1. 介紹

JDK1.5中引入了對java語言的多種擴展,泛型(generics)即其中之一。

這個教程的目標是向您介紹java的泛型(generic)。你可能熟悉其他語言的泛型,最著名的是C++的模板(templates)。如果這樣,你很快就會看到兩者的相似之處和重要差異。如果你不熟悉相似的語法結構,那么更好,你可以從頭開始而不需要忘記誤解。

Generics允許對類型進行抽象(abstract over types)。最常見的例子是集合類型(Container types),Collection的類樹中任意一個即是。

下面是那種典型用法:

???????List myIntList =?new?LinkedList();// 1

????????myIntList.add(new?Integer(0));// 2

???????Integer x = (Integer)?myIntList.iterator().next();// 3

第3行的類型轉換有些煩人。通常情況下,程序員知道一個特定的list里邊放的是什么類型的數據。但是,這個類型轉換是必須的(essential)。編譯器只能保證iterator返回的是Object類型。為了保證對Integer類型變量賦值的類型安全,必須進行類型轉換。

當然,這個類型轉換不僅僅帶來了混亂,它還可能產生一個運行時錯誤(run time error),因為程序員可能會犯錯。

程序員如何才能明確表示他們的意圖,把一個list中的內容限制為一個特定的數據類型呢?這是generics背后的核心思想。這是上面程序片斷的一個泛型版本:

???????List<Integer> myIntList =?new?LinkedList<Integer>();?// 1

???????myIntList.add(new?Integer(0));?// 2

???????Integer x =?myIntList.iterator().next();?// 3

注意變量myIntList的類型聲明。它指定這不是一個任意的List,而是一個Integer的List,寫作:List<Integer>。我們說List是一個帶一個類型參數的泛型接口(a generic interface that takes a type parameter),本例中,類型參數是Integer。我們在創建這個List對象的時候也指定了一個類型參數。

另一個需要注意的是第3行沒了類型轉換。

現在,你可能認為我們已經成功地去掉了程序里的混亂。我們用第1行的類型參數取代了第3行的類型轉換。然而,這里還有個很大的不同。編譯器現在能夠在編譯時檢查程序的正確性。當我們說myIntList被聲明為List<Integer>類型,這告訴我們無論何時何地使用myIntList變量,編譯器保證其中的元素的正確的類型。與之相反,一個類型轉換說明程序員認為在那個代碼點上它應該是那種類型。

實際結果是,這可以增加可讀性和穩定性(robustness),尤其在大型的程序中。

2.定義簡單的泛型

下面是從java.util包中的List接口和Iterator接口的定義中摘錄的片斷:

public?interface?List<E> {

???????????void?add(E x);

???????????Iterator<E>?iterator();

}

public?interface?Iterator<E> {

???????????E?next();

???????????boolean?hasNext();

}

這些都應該是很熟悉的,除了尖括號中的部分,那是接口List和Iterator中的形式類型參數的聲明(the declarations of the formal type parameters of the interfaces List and Iterator)。

類型參數在整個類的聲明中可用,幾乎是所有可是使用其他普通類型的地方(但是有些重要的限制,請參考第7部分)。

(原文:Type parameters can be used throughout the generic declaration, pretty much where you would use ordinary types (though there are some important restrictions; see section 7))

?

在介紹那一節我們看到了對泛型類型聲明List(the generic type declaration List)的調用,如List<Integer>。在這個調用中(通常稱作一個參數化類型a parameterized type),所有出現形式類型參數(formal type parameter,這里是E)都被替換成實體類型參數(actual type argument)(這里是Integer)。

你可能想象,List<Integer>代表一個E被全部替換成Integer的版本:

public?interface?IntegerList {

void?add(Integer x)

Iterator<Integer>?iterator();

}

這種直覺可能有幫助,但是也可能導致誤解。

它有幫助,因為List<Integer>的聲明確實有類似這種替換的方法。

它可能導致誤解,因為泛型聲明絕不會實際的被這樣替換。沒有代碼的多個拷貝,源碼中沒有、二進制代碼中也沒有;磁盤中沒有,內存中也沒有。如果你是一個C++程序員,你會理解這是和C++模板的很大的區別。

一個泛型類型的聲明只被編譯一次,并且得到一個class文件,就像普通的class或者interface的聲明一樣。

? ? ? ? 類型參數就跟在方法或構造函數中普通的參數一樣。就像一個方法有形式參數(formal value parameters)來描述它操作的參數的種類一樣,一個泛型聲明也有形式類型參數(formal type parameters)。當一個方法被調用,實參(actual arguments)替換形參,方法體被執行。當一個泛型聲明被調用,實際類型參數(actual type arguments)取代形式類型參數。

? ? ? ? 一個命名的習慣:我們推薦你用簡練的名字作為形式類型參數的名字(如果可能,單個字符)。最好避免小寫字母,這使它和其他的普通的形式參數很容易被區分開來。許多容器類型使用E作為其中元素的類型,就像上面舉的例子。在后面的例子中還會有一些其他的命名習慣。

3.泛型和子類繼承

讓我們測試一下我們對泛型的理解。下面的代碼片斷合法么?

List<String> ls = new ArrayList<String>(); //1

List<Object> lo = ls; //2

第1行當然合法,但是這個問題的狡猾之處在于第2行。

這產生一個問題:

一個String的List是一個Object的List么?大多數人的直覺是回答:“當然!”。

好,在看下面的幾行:

lo.add(new Object()); // 3

String s = ls.get(0); // 4:?試圖把Object賦值給String

這里,我們使用lo指向ls。我們通過lo來訪問ls,一個String的list。我們可以插入任意對象進去。結果是ls中保存的不再是String。當我們試圖從中取出元素的時候,會得到意外的結果。

java編譯器當然會阻止這種情況的發生。第2行會導致一個編譯錯誤。

總之,如果Foo是Bar的一個子類型(子類或者子接口),而G是某種泛型聲明,那么G<Foo>是G<Bar>的子類型并不成立!!

這可能是你學習泛型中最難理解的部分,因為它和你的直覺相反。

這種直覺的問題在于它假定這個集合不改變。我們的直覺認為這些東西都不可改變。

舉例來說,如果一個交通部(DMV)提供一個駕駛員里表給人口普查局,這似乎很合理。我們想,一個List<Driver>是一個List<Person>,假定Driver是Person的子類型。實際上,我們傳遞的是一個駕駛員注冊的拷貝。然而,人口普查局可能往駕駛員list中加入其他人,這破壞了交通部的記錄。

為了處理這種情況,考慮一些更靈活的泛型類型很有用。到現在為止我們看到的規則限制比較大。

4.通配符(Wildcards)

考慮寫一個例程來打印一個集合(Collection)中的所有元素。下面是在老的語言中你可能寫的代碼:

????????????void?printCollection(Collection c) {

?????????????????Iterator i =?c.iterator();

?????????????????for?(int?k = 0; k < c.size(); k++) {

???????????????????????System.out.println(i.next());

??????????????????}

}?

下面是一個使用泛型的幼稚的嘗試(使用了新的循環語法):

??????void?printCollection(Collection<Object> c) {

???????????for?(Object e : c) {

?????????????????System.out.println(e);

???????????}

}?

問題是新版本的用處比老版本小多了。老版本的代碼可以使用任何類型的collection作為參數,而新版本則只能使用Collection<Object>,我們剛才闡述了,它不是所有類型的collections的父類。

那么什么是各種collections的父類呢?它寫作:?Collection<?>(發音為:"collection of unknown"),就是,一個集合,它的元素類型可以匹配任何類型。顯然,它被稱為通配符。我們可以寫:

void?printCollection(Collection<?> c) {

for?(Object e : c) {

System.out.println(e);

}

}

現在,我們可以使用任何類型的collection來調用它。注意,我們仍然可以讀取c中的元素,其類型是Object。這永遠是安全的,因為不管collection的真實類型是什么,它包含的都是objects。但是將任意元素加入到其中不是類型安全的:

Collection<?> c =?new?ArrayList<String>();

c.add(new?Object());?//?編譯時錯誤

因為我們不知道c的元素類型,我們不能向其中添加對象。

add方法有類型參數E作為集合的元素類型。我們傳給add的任何參數都必須是一個未知類型的子類。因為我們不知道那是什么類型,所以我們無法傳任何東西進去。唯一的例外是null,它是所有類型的成員。

另一方面,我們可以調用get()方法并使用其返回值。返回值是一個未知的類型,但是我們知道,它總是一個Object,因此把get的返回值賦值給一個Object類型的對象或者放在任何希望是Object類型的地方是安全的。

4.1.有限制的通配符(Bounded Wildcards)

考慮一個簡單的畫圖程序,它可以用來畫各種形狀,比如矩形和圓形。

為了在程序中表示這些形狀,你可以定義下面的類繼承結構:

public?abstract?class?Shape {

public?abstract?void?draw(Canvas c);

}

public?class?Circle?extends?Shape {

private?int????x,?y,?radius;

public?void?draw(Canvas c) {?// ...

}

}

public?class?Rectangle?extends?Shape {

private?int????x,?y,?width,?height;

public?void?draw(Canvas c) {

// ...

}

}

這些類可以在一個畫布(Canvas)上被畫出來:

public?class?Canvas {

public?void?draw(Shape s) {

s.draw(this);

}

}

所有的圖形通常都有很多個形狀。假定它們用一個list來表示,Canvas里有一個方法來畫出所有的形狀會比較方便:

??????public?void?drawAll(List<Shape> shapes) {

??????????for?(Shape s : shapes) {

?????????????s.draw(this);

?????????}

}

現在,類型規則導致drawAll()只能使用Shape的list來調用。它不能,比如說對List<Circle>來調用。這很不幸,因為這個方法所作的只是從這個list讀取shape,因此它應該也能對List<Circle>調用。我們真正要的是這個方法能夠接受一個任意種類的shape:

public?void?drawAll(List<??extends?Shape> shapes) {?//..}

這里有一處很小但是很重要的不同:我們把類型?List<Shape>?替換成了?List<??extends?Shape>。現在drawAll()可以接受任何Shape的子類的List,所以我們可以對List<Circle>進行調用。

List<??extends?Shape>是有限制通配符的一個例子。這里?代表一個未知的類型,就像我們前面看到的通配符一樣。但是,在這里,我們知道這個未知的類型實際上是Shape的一個子類(它可以是Shape本身或者Shape的子類而不必是extends自Shape)。我們說Shape是這個通配符的上限(upper bound)。

像平常一樣,要得到使用通配符的靈活性有些代價。這個代價是,現在像shapes中寫入是非法的。比如下面的代碼是不允許的:

?????????public?void?addRectangle(List<??extends?Shape> shapes) {

???????shapes.add(0,?new?Rectangle());?// compile-time error!

????}

你應該能夠指出為什么上面的代碼是不允許的。因為shapes.add的第二個參數類型是??extends?Shape?——一個Shape未知的子類。因此我們不知道這個類型是什么,我們不知道它是不是Rectangle的父類;它可能是也可能不是一個父類,所以這里傳遞一個Rectangle不安全。

有限制的通配符正是我們解決DMV給人口普查局傳送名單的例子所需要的。我們的例子假定數據用一個姓名(String)到people(用Person或其子類來表示,比如Driver)。Map<K,V>是一個有兩個類型參數的泛型類型的例子,表示map的鍵key和值value。

再一次,注意形式類型參數的命名習慣——K代表keys,V代表vlaues。

public?class?Census?{

public?static void??addRegistry(Map<String, ??extends?Person>?registry)?{?...}

}...

Map<String, Driver>?allDrivers = ...;

Census.addRegistry(allDrivers);

5.泛型方法

考慮寫一個方法,它用一個Object的數組和一個collection作為參數,完成把數組中所有object放入collection中的功能。

下面是第一次嘗試:

static?void?fromArrayToCollection(Object[] a, Collection<?>?c)?{

for?(Object o : a)?{

c.add(o);?//?編譯期錯誤

}

}

現在,你應該能夠學會避免初學者試圖使用Collection<Object>作為集合參數類型的錯誤了?;蛟S你已經意識到使用?Collection<?>也不能工作。會議一下,你不能把對象放進一個未知類型的集合中去。

解決這個問題的辦法是使用generic methods。就像類型聲明,方法的聲明也可以被泛型化——就是說,帶有一個或者多個類型參數。

static?<T>?void?fromArrayToCollection(T[] a, Collection<T> c){

???????for?(T o : a) {

???????????c.add(o);?// correct

???????}

????}

我們可以使用任意集合來調用這個方法,只要其元素的類型是數組的元素類型的父類。

??????Object[] oa =?new?Object[100];

??????Collection<Object> co =?new?ArrayList<Object>();

??????fromArrayToCollection(oa, co);// T?指Object

??????String[] sa =?new?String[100];

??????Collection<String> cs =?new?ArrayList<String>();

??????fromArrayToCollection(sa, cs);// T inferred to be String

??????fromArrayToCollection(sa, co);// T inferred to be Object

??????Integer[] ia =?new?Integer[100];

??????Float[] fa =?new?Float[100];

??????Number[] na =?new?Number[100];

??????Collection<Number> cn =?new?ArrayList<Number>();

??????fromArrayToCollection(ia, cn);// T inferred to be Number

??????fromArrayToCollection(fa, cn);// T inferred to be Number

??????fromArrayToCollection(na, cn);// T inferred to be Number

??????fromArrayToCollection(na, co);// T inferred to be Object

??????fromArrayToCollection(na, cs);// compile-time error

注意,我們并沒有傳送真實類型參數(actual type argument)給一個泛型方法。編譯器根據實參為我們推斷類型參數的值。它通常推斷出能使調用類型正確的最明確的類型參數(原文是:It will generally?infer?the most specific type argument that will make the call type-correct.)。

現在有一個問題:我們應該什么時候使用泛型方法,又什么時候使用通配符類型呢?

為了理解答案,讓我們先看看Collection庫中的幾個方法。

public?interface?Collection<E> {

????boolean?containsAll(Collection<?> c);

????boolean?addAll(Collection<??extends?E> c);

}

我們也可以使用泛型方法來代替:

public?interface?Collection<E> {

????????<T>?boolean?containsAll(Collection<T> c);

????????<T?extends?E>?boolean?addAll(Collection<T> c);

????????//??hey, type variables can have bounds too!

}

但是,在?containsAll?和?addAll中,類型參數T?都只使用一次。返回值的類型既不依賴于類型參數(type parameter)也不依賴于方法的其他參數(這里,只有簡單的一個參數)。這告訴我們類型參數(type argument)被用作多態(polymorphism),它唯一的效果是允許在不同的調用點,可以使用多種實參類型(actual argument)。如果是這種情況,應該使用通配符。通配符就是被設計用來支持靈活的子類化的,這是我們在這里要強調的。

泛型函數允許類型參數被用來表示方法的一個或多個參數之間的依賴關系,或者參數與其返回值的依賴關系。如果沒有這樣的依賴關系,不應該使用泛型方法。

(原文:Generic methods allow?type?parameters to be used to express dependencies among the types of one or more?arguments?to a method and/or its return type. If there isn’t such a dependency, a generic method should not be used.)

一前一后的同時使用泛型方法和通配符也是可能的。下面是方法?Collections.copy():

class?Collections?{

public?static?<T>??void?copy(List<T>?dest, List<??extends?T>?src){...}

}

注意兩個參數的類型的依賴關系。任何被從源list從拷貝出來的對象必須能夠將其指定為目標list(dest)?的元素的類型——T類型。因此源類型的元素類型可以是T的任意子類型,我們不關心具體的類型。

copy方法的簽名使用一個類型參數表示了類型依賴,但是使用了一個通配符作為第二個參數的元素類型。我們也可以用其他方式寫這個函數的簽名而根本不使用通配符:

class?Collections?{

public?static?<T, S?extends?T>??void?copy(List<T>?dest, List<S>?src){...}

}

這也可以,但是第一個類型參數在dst的類型和第二個參數的類型參數S的上限這兩個地方都有使用,而S本身只使用一次,在src的類型中——沒有其他的依賴于它。這意味著我們可以用通配符來代替S。使用通配符比聲明顯式的類型參數更加清晰和準確,所以在可能的情況下使用通配符更好。

通配符還有一個優勢式他們可以在方法簽名之外被使用,比如field的類型,局部變量和數組。這就有一個例子。

回到我們的畫圖問題,假定我們想要保持畫圖請求的歷史記錄。我們可以把歷史記錄保存在Shape類的一個靜態成員變量里,在drawAll()?被調用的時候把傳進來的參數保存進歷史記錄:

static?List<List<??extends?Shape>> history = new ArrayList<List<??extends?Shape>>();

public?void?drawAll(List<??extends?Shape> shapes) {

history.addLast(shapes);

for?(Shape s: shapes) {

s.draw(this);

}

}

最終,再說一下類型參數的命名習慣。

我們使用T?代表類型,無論何時都沒有比這更具體的類型來區分它。這經常見于泛型方法。如果有多個類型參數,我們可能使用字母表中T的臨近的字母,比如S。如果一個泛型函數在一個泛型類里邊出現,最好避免在方法的類型參數和類的類型參數中使用同樣的名字來避免混淆。對內部類也是同樣。

6.與舊代碼交互

直到現在,我們的例子中都假定了一個理想的世界,那里所有人使用的都是最新版本的java編程語言,它支持泛型。

唉,現實并非如此。百萬行代碼都是在早先版本的語言下寫作的,他們不可能一晚上就轉換過來。

后面,在第10部分,我們會解決把老代碼轉換為使用泛型的代碼的問題。在這里,我們把注意力放在一個更簡單的問題:老代碼怎么和泛型代碼交互?這個問題包括兩部分:在泛型中使用老代碼和在老代碼中使用泛型代碼。

6.1.在泛型代碼中使用老代碼

怎樣才能使用老代碼的同時在自己的代碼中享受泛型帶來的好處?

作為一個例子,假定你像使用包?com.Fooblibar.widgets。Fooblibar.com(完全虛構出來的公司)?的人們出售一種進行庫存管理的系統,下面是主要代碼:

package?com.Fooblibar.widgets;

public?interface?Part?{?...}

public?class?Inventory?{

/**

*?添加一個新配件到庫存數據庫

*?配件有名字name,?并由零件(Part)的集合組成。

*?零件由parts?指定. collection parts?中的元素必須實現Part接口。

**/

public?static void?addAssembly(String name, Collection parts)?{...}?public static?Assembly getAssembly(String name)?{...}

}

public?interface?Assembly?{

Collection?getParts();?// Returns a collection of Parts

}

現在,你想使用上述API寫新代碼。如果能保證調用addAssembly()時總是使用正確的參數會很棒——就是說,你傳進去的確實時一個Part的Collection。當然,泛型可以實現這個目的:

package?com.mycompany.inventory;

import?com.Fooblibar.widgets.*;

public?class?Blade implements Part?{

...

}

public?class?Guillotine implements Part?{

}

public?class?Main?{

public?static void?main(String[] args)?{

Collection<Part>?c = new ArrayList<Part>();

c.add(new Guillotine()) ;

c.add(new Blade());

Inventory.addAssembly(”thingee”, c);

Collection<Part>?k =?Inventory.getAssembly(”thingee”).getParts();

}

}

當我們調用addAssembly,它希望第二個參數是Collection類型。而實際參數是Collection<Part>?類型。這可以工作,但是為什么?畢竟,大多數集合不包含Part對象,而且總的來說,編譯器無法知道Collection指的是什么類型的集合。

在嚴格的泛型代碼里,Collection應該總是帶著類型參數。當一個泛型類型,比如Collection被使用而沒有類型參數時,它被稱作一個raw type(自然類型??)。

大多數人的第一直覺時Collection實際上意味著?Collection<Object>。但是,像我們前面看到的,當需要Collection<Object>時傳遞?Collection<Part>是不安全的。類型Collection表示一個未知類型元素的集合,就像Collection<?>,這樣說更準確。

但是等一下,那也不正確。考慮getParts()這個調用,它返回一個Collection。然后它被賦值給k,而k是Collection<Part>。如果這個調用的結果是一個Collection<?>,這個賦值應該是一個錯誤。

事實上,這個賦值是合法的,但是它產生一個未檢查警告(unchecked warning)。這個警告是必要的,因為事實是編譯器無法保證其正確性。我們沒有辦法檢查getAssembly()中的舊代碼來保證返回的確實是一個Collection<Part>。代碼里使用的類型是Collection,可以合法的向其中加入任何Object。

那么,這應該是一個錯誤么?理論上講,Yes,但是實際上講,如果泛型代碼要調用舊代碼,那么這必須被允許。這取決于你,程序員,在這種情況下來滿足你自己。這個賦值是合法的因為getAssembly()的調用約定中說它返回一個Part的集合,即使這個類型聲明中沒有顯示出這一點。

因此,自然類型和通配符類型很像,但是他們的類型檢查不是同樣嚴格。允許泛型與已經存在的老代碼相交互是一個深思熟慮的決定。

從泛型代碼中調用老代碼具有先天的危險性,一旦你把泛型編程和非泛型編程混合起來,泛型系統所提供的所有安全保證都失效。然而,你還是比你根本不用泛型要好。至少你知道你這一端的代碼是穩定的。

在非泛型代碼遠比泛型代碼多的時候,不可避免會出現兩者必須混合的情況。

如果你發現你不得不混合舊代碼和泛型代碼,仔細注意未檢查警告(unchecked warnings),仔細考慮你怎樣才能證明出現警告的部分代碼是正確的。

如果你仍然犯了錯,而導致警告的代碼確實不是類型安全的,那么會發生什么?讓我們看一下這種情形。在這個過程中,我們將了解一些編譯器工作的內幕。

6.2.擦除和翻譯(Erasure and Translation)

public?String loophole(Integer x) {

???????List<String> ys =?new?LinkedList<String>();

???????List xs = ys;

???????xs.add(x);?// compile-time unchecked warning

???????return?ys.iterator().next();

}

這里,我們用一個老的普通的list的引用來指向一個String的list。我們插入一個Integer到這個list中,并且試圖得到一個String。這是明顯的錯誤。如果我們忽略這個警告并且試圖運行以上代碼,它將在我們試圖使用錯誤的類型的地方失敗。在運行的時候,上面的代碼與下面的代碼的行為一樣:

public?String loophole(Integer x) {

???????List ys =?new?LinkedList();

???????List xs = ys;

???????xs.add(x);

???????return?(String) ys.iterator().next();?// run time error

}

當我們從list中獲取一個元素的時候,并且試圖通過轉換為String而把它當作一個string,我們得到一個?ClassCastException。完全一樣的事情發生在使用泛型的代碼上。

這樣的原因是,泛型是通過java編譯器的稱為擦除(erasure)的前端處理來實現的。你可以(基本上就是)把它認為是一個從源碼到源碼的轉換,它把泛型版本的loophole()轉換成非泛型版本。

結果是,java虛擬機的類型安全和穩定性決不能冒險,即使在又unchecked warning的情況下。

(原文:As a result, the type safety and integrity of the Java virtual machine are never at risk, even in the presence of unchecked warnings.)

基本上,擦除去掉了所有的泛型類型信息。所有在尖括號之間的類型信息都被扔掉了,因此,比如說一個List<String>類型被轉換為List。所有對類型變量的引用被替換成類型變量的上限(通常是Object)。而且,無論何時如果結果代碼類型不正確,會插入一個到合適的類型的轉換,就像loophole的最后一行那樣。

擦除的全部的細節超出了本文的范圍,但是我們給出的簡單描述與事實很接近。知道一點這個有好處,特別是如果你要作一些復雜的事,比如把現有API轉換成使用泛型的代碼(第10部分)或者僅僅是想理解為什么會這樣。

6.3.在老代碼中使用泛型代碼

現在讓我們來考慮相反的情形。假定Fooblibar.com公司的人決定把他們的代碼轉換為使用泛型來實現,但是他們的一些客戶沒有轉換。現在代碼就像下面:

package?com.Fooblibar.widgets;

public?interface?Part?{?...}

public?class?Inventory?{

?/**

* Adds a new Assembly to the inventory database.

* The assembly is given the name name, and consists of a set

*?parts?specified by parts. All elements of the collection parts

* must support the Part interface.

**/

public?static void?addAssembly(String name, Collection<Part>?parts)?{...}

public?static?Assembly getAssembly(String name)?{...}

}

public?interface?Assembly?{

Collection<Part>?getParts();?// Returns a collection of Parts

}

客戶端代碼如下:

package?com.mycompany.inventory;

import?com.Fooblibar.widgets.*;

public?class?Blade implements Part?{

...

}

public?class?Guillotine implements Part?{

}

public?class?Main?{

public?static void?main(String[] args)?{

Collection c = new?ArrayList();

c.add(new Guillotine()) ;

c.add(new Blade());

Inventory.addAssembly(”thingee”, c);?// 1: unchecked warning

Collection k =?Inventory.getAssembly(”thingee”).getParts();

}

}

客戶端代碼是在泛型被引入之前完成的,但是它使用了包com.Fooblibar.widgets和集合庫,它們都使用了泛型??蛻舳舜a中的泛型類的聲明都是使用了自然類型(raw types)。第1行產生一個unchecked warning,因為一個自然的Collection被傳遞到一個需要Collection<Part>的地方,而編譯器無法保證Collection就是一個Collection<Part>。

你還有另一種選擇,你可以使用source 1.4?標志來編譯客戶端代碼,以保證不會產生警告。但是這種情況下你無法使用jdk1.5?中的任何新特性。

7.要點(The Fine Print)

7.1.一個泛型類被其所有調用共享

下面的代碼打印的結果是什么?

???????List<String> l1 =?new?ArrayList<String>();

???????List<Integer> l2 =?new?ArrayList<Integer>();

???????System.out.println(l1.getClass() == l2.getClass());

或許你會說false,但是那你就錯了。它打印出true。因為所有的泛型類型在運行時有同樣的類(class),而不管他們的實際類型參數。

事實上,泛型之所以為泛型就是因為它對所有其可能的類型參數,它有同樣的行為;同樣的類可以被當作許多不同的類型。

作為一個結果,類的靜態變量和方法也在所有的實例間共享。這就是為什么在靜態方法或靜態初始化代碼中或者在靜態變量的聲明和初始化時使用類型參數申明是不合法的原因。

(原文:As consequence, the static variables and methods of a class are also shared among all the instances. That is why it is illegal to refer to the type parameters of a type declaration in a static method or initializer, or in the declaration or initializer of a static variable.)

7.2.?????轉型和instanceof

泛型類被所有其實例(instances)共享的另一個暗示是檢查一個實例是不是一個特定類型的泛型類是沒有意義的。

???????Collection cs =?new?ArrayList<String>();

???????if?(cs?instanceof?Collection<String>) { ...}?//?非法

類似的,如下的類型轉換

Collection<String> cstr = (Collection<String>) cs;

得到一個unchecked warning,因為運行時環境不會為你作這樣的檢查。

對類型變量也是一樣:

??????<T> T?badCast(T t, Object o) {

?????????return?(T) o;?// unchecked warning

??}

類型參數在運行時并不存在。這意味著它們不會添加任何的時間或者空間上的負擔,這很好。不幸的是,這也意味著你不能依靠他們進行類型轉換。

7.3.數組Arrays

數組對象的組成類型不能是一個類型變量或者類型參數,除非它是無上限的通配符類型。你可以聲明元素類型是一個類型參數或者參數化類型的數組類型,但不是數組對象(譯注:得不到對象,只能聲明)。

(原文:The component type of an array object may not be a type variable or a parameterized type, unless it is an (unbounded) wildcard type.You can declare array types whose element type is a type variable or a parameterized type, but not array objects.)

這很煩人,但是確實時這樣。為了避免下面的情況,必須有這樣的限制:

List<String>[] lsa = new List<String>[10]; // not really allowed

Object o = lsa;

Object[] oa = (Object[]) o;

List<Integer> li = new ArrayList<Integer>();

li.add(new Integer(3));

oa[1] = li; // unsound, but passes run time store check

String s =?lsa[1].get(0); // run-time error - ClassCastException

如果參數化類型可以是數組,那么意味著上面的例子可以沒有任何unchecked warnings的通過編譯,但是在運行時失敗。我們把類型安全(type-safety)作為泛型首要的設計目標。特別的,java語言被設計為保證:如果你的整個程序沒有unchecked warnings的使用javac –source1.5通過編譯,那么它是類型安全的(原文: if your entire application has been compiled without unchecked warnings using javac -source 1.5, it is type safe)。

然和,你仍然可以使用通配符數組。上面的代碼有兩種變化。第一種改變放棄使用數組對象和元素類型參數化的數組類型。結果是,我們不得不顯式的進行類型轉換來從數組中獲得一個String。

List<?>[] lsa = new List<?>[10]; // ok, array of unbounded wildcard type

Object o = lsa;

Object[] oa = (Object[]) o;

List<Integer> li = new ArrayList<Integer>();

li.add(new Integer(3));

oa[1] = li; // correct

String s = (String)?lsa[1].get(0); // run time error, but cast is explicit

在下面的變體中,我們避免了產生一個元素類型是參數化的數組對象,但是使用了元素類型參數化的類型。(譯注:意思如下面的第一行代碼所示,聲明一個泛型化的數組,但是new的時候使用的是raw type,原文中是?new ArrayList<?>(10),那是錯的,已經修正為new ArrayList(10);)這是合法的,但是產生一個unchecked warning。實際上,這個代碼是不安全的,最后產生一個錯誤。

???????List<String>[] lsa =?new?ArrayList[10];?// unchecked warning - this is unsafe!

??????????????Object o = lsa;

??????????????Object[] oa = (Object[]) o;

??????????????List<Integer> li =?new?ArrayList<Integer>();

??????????????li.add(new?Integer(3));

??????????????oa[1] = li;?// correct

??????????????String s =?lsa[1].get(0);?// run time error, but we were warned

類似的,創建一個元素類型是一個類型變量的數組對象導致一個編譯時錯誤:

????????<T>?T[] makeArray(T t) {

???????????return?new?T[100];?// error

}

因為類型變量在運行時并不存在,所以沒有辦法決定實際類型是什么。

解決這些限制的辦法是使用字面的類作為運行時類型標志(原文:use class literals as run time type tokens),見第8部分。

8.???Class Literals as Run-time Type Tokens

JDK1.5中一個變化是類?java.lang.Class是泛型化的。這是把泛型作為容器類之外的一個很有意思的例子(using genericity for something other than a container class)。

現在,Class有一個類型參數T,?你很可能會問,T?代表什么?

它代表Class對象代表的類型。比如說,String.class類型代表?Class<String>,Serializable.class代表?Class<Serializable>。著可以被用來提高你的反射代碼的類型安全。

特別的,因為?Class的?newInstance()?方法現在返回一個T,?你可以在使用反射創建對象時得到更精確的類型。

比如說,假定你要寫一個工具方法來進行一個數據庫查詢,給定一個SQL語句,并返回一個數據庫中符合查詢條件的對象集合(collection)。

一個方法時顯式的傳遞一個工廠對象,像下面的代碼:

????????interface?Factory<T> {

???????????public?T[] make();

}

public?<T> Collection<T> select(Factory<T> factory, String statement) {

Collection<T> result =?new?ArrayList<T>();

????????????/* run sql query using jdbc */

????????????for?(int?i=0;i<10;i++/* iterate over jdbc results */?) {

????????????????T item =?factory.make();

????????????/* use reflection and set all of item’s fields from sql results */

????????????????result.add(item);

????????????}

????????????return?result;

}

你可以這樣調用:

select(new Factory<EmpInfo>(){

public?EmpInfo make()?{

return?new EmpInfo();

}

}?,?”selection string”);

也可以聲明一個類?EmpInfoFactory?來支持接口?Factory:

class?EmpInfoFactory?implements?Factory<EmpInfo>?{?...

public?EmpInfo make()?{?return?new EmpInfo();}

}

然后調用:

select(getMyEmpInfoFactory(), "selection string");

這個解決方案的缺點是它需要下面的二者之一:

l?????????調用處那冗長的匿名工廠類,或

l?????????為每個要使用的類型聲明一個工廠類并傳遞其對象給調用的地方

這很不自然。

使用class literal作為工廠對象是非常自然的,它可以被發射使用。沒有泛型的代碼可能是:

Collection emps =?sqlUtility.select(EmpInfo.class, ”select * from emps”); ...

public?static?Collection select(Class c, String sqlStatement)?{

Collection result = new?ArrayList();

/* run sql query using jdbc */

for?(?/* iterate over jdbc results */?)?{

Object item =?c.newInstance();

/* use reflection and set all of item’s fields from sql results */

result.add(item);

}

return?result;

}

但是這不能給我們返回一個我們要的精確類型的集合。現在Class是泛型的,我們可以寫:

Collection<EmpInfo>?emps=sqlUtility.select(EmpInfo.class, ”select * from emps”); ...

public?static?<T>?Collection<T>?select(Class<T>c, String sqlStatement)?{

Collection<T>?result = new ArrayList<T>();

/* run sql query using jdbc */

for?(?/* iterate over jdbc results */?)?{

T item =?c.newInstance();

/* use reflection and set all of item’s fields from sql results */

result.add(item);

}

return?result;

}

來通過一種類型安全的方式得到我們要的集合。

這項技術是一個非常有用的技巧,它已成為一個在處理注釋(annotations)的新API中被廣泛使用的習慣用法。

9.More fun with *

在這一部分,我們來考慮一些通配符得高級用法。我們已經看到了上限通配符在從一個數據結構中進行讀取的幾個例子?,F在考慮相反的情況,一個只寫的數據結構。

接口Sink是這種情況的一個簡單例子。

????????????interface?Sink<T> {

??????????????void?flush(T t);

????}

我們可以想象他被如下面的代碼一樣使用。方法writeAll()?被設計來把集合coll的所有元素flush到sink snk,并且返回最后一個flush的元素。

????????public?static?<T> T writeAll(Collection<T> coll, Sink<T> snk) {

???????????T last =?null;

???????????for?(T t : coll) {

???????????????last?= t;

???????????????snk.flush(last);

???????????}

????????????return?last;

}

Sink<Object>?s;

Collection<String>?cs;

String str = writeAll(cs, s);?//?非法的調用!!

像上面所寫,writeAll()?的調用是非法的,因為沒有有效的類型參數可以被推斷出來。String?或?Object都不是T的合適的類型,因為Collection的元素和?Sink的元素必須是同樣的類型。

我們可以解決這個問題,通過使用通配符來修改writeAll()的方法簽名,如下:

<T> T?writeAll(Collection<??extends?T> coll, Sink<T> snk) {?… }

String str = writeAll(cs, s);?//可以調用但是返回值類型錯誤

這個調用現在是合法的,但是賦值產生錯誤,因為推斷出的返回值類型是?Object因為T?匹配了Sink的類型,Object。

解決方案是使用一種我們還沒有見過的有限制的通配符:有下限的通配符。語法?? super T?表示T的一個未知的父類(或者是T自己)。這跟我們用? extends T?表示T的一個未知的子類是對應的。

<T> T?writeAll(Collection<T> coll, Sink<??super?T> snk) {?… }

String str =?writeAll(cs, s);?// YES!!!

使用這個語法,這個調用是合法的,推斷出來的T是String,正是我們想要的。

現在讓我們看一個更現實的例子。一個?java.util.TreeSet<E>?代表一個有序的元素是E類型的樹。創建一個TreeSet的一個方法是傳遞一個?Comparator?對象給構造函數。這個Comparator將會用來按照需要對TreeSet進行排序。

TreeSet(Comparator<E>?c)

Comparator?接口是核心:

interface?Comparator<T>?{???int?compare(T fst, T snd);???}

假定我們要創建一個?TreeSet<String>?并傳遞一個合適的?Comparator,我們需要傳一個能比較String的Comparator。這可以是一個?Comparator<String>,也可以是一個?Comparator<Object>。然而我們不能用Comparator<Object>來調用上面的構造函數。我們可以使用一個有下限的通配符來得到我們需要的靈活性:

TreeSet(Comparator<??super?E>?c)

這允許任何可用的Comparator被傳遞進去。

作為使用下限通配符最終的例子,讓我們來看看方法?Collections.max(),它返回一個集合中的最大的元素。

現在,為了讓max()能工作,傳進來的集合中的所有元素必須實現?Comparatable接口。而且,他們必須都能夠被彼此比較(all be comparable to?each other)。第一個嘗試是:

public?static?<T?extends?Comparable<T>>??T max(Collection<T>?coll)

就是說,方法的參數是某一個能和自己進行比較的T的集合。這限制太嚴格了。

為什么?考慮一個能和任何對象進行比較的類型:

class?Foo?implements?Comparable<Object>?{...}?...

Collection<Foo>?cf = ...;

Collections.max(cf);?//?應該能工作

cf?中的每個元素都可以和每個cf中的其他元素進行比較,因為每個這樣的元素都是一個Foo,它可以和任意的對象進行比較,也可以和另一個Foo進行比較。

但是,使用上面的方法簽名,我們發現這個調用被拒絕。推斷出來的類型必須是Foo,但是Foo沒有實現接口?Comparable<Foo>。

T?精確的(exactly)和自己能比較是不需要的。所需要的是?T能夠和它的父類中的一個進行比較,這導出:(注:Collections.max()的實際方法簽名更復雜,我們在第10部分再討論。)

public?static?<T?extends?Comparable<??super?T>>?T max(Collection<T>?coll)

這個推論對大多數想讓?Comparable?對任意類型生效的用法中都有效:你總是應該使用?Comparable<? super T>。

總之,如果你有一個只使用類型參數T作為參數的API,它的使用應該利用下限通配符( ? super T )的好處。相反的,如果API只返回T,你應該使用上限通配符( ? extends T )來給你的客戶端更大的靈活性。

(原文:This reasoning applies to almost any usage of Comparable that is intended to work for arbitrary types: You always want to use Comparable<??super?T>.

In general, if you have an API that only uses a type parameter T as an argument, its uses should take advantage of lower bounded wildcards (? super T). Conversely, if the API only returns T, you'll give your clients more flexibility by using upper bounded wildcards (? extends T).?)。

9.1.通配符匹配(wildcard capture)

現在應該很清晰,如果給定:

Set<?> unknownSet = new HashSet<String>(); ...

/**?向?Set s?中添加一個元素*/

public?static <T> void addToSet(Set<T> s, T t) {...}

這個調用是非法的:

addToSet(unknownSet, "abc"); //?非法

實際的set是一個String的set并不起作用,起作用的是傳進來的表達式是一個unknown type的set,它不能保證是一個String的set或者任何其他的特定類型。

現在,考慮:

class?Collections?{?...

<T>?public static?Set<T>?unmodifiableSet(Set<T>?set)?{?...?}

}...

Set<?>?s =?Collections.unmodifiableSet(unknownSet);?// this works! Why?

似乎這應該不被允許,但是,研究這個特定的調用,允許它是非常安全的。畢竟,unmodifiableSet?確實對任何種類的Set能工作,不管它的元素類型。

因為這種情況相對出現的次數比較多,有一個特殊的規則在能證明代碼是安全的情況下允許這樣的代碼。()這個規則,稱為wildcard capture,允許編譯器推斷出通配符為unknown type作為一個泛型方法的類型參數。

(原文:Because this situation arises relatively frequently, there is a special rule that allows such code under very specific circumstances in which the code can be proven to be safe. This rule, known as wildcard capture, allows the compiler to infer the unknown type of a wildcard as a type argument to a generic method.)

10.泛型化老代碼

前面,我們講述了新老代碼如何交互?,F在,是時候研究更難的泛型化老代碼的問題了。

如果你決定把老代碼轉換成使用泛型的代碼,你需要仔細考慮怎么修改你的API。

你必須確定泛型化的API不會過分嚴格,它必須繼續支持原來的API調用契約(original contract of the API)。在考慮幾個?java.util.Collection中的例子。泛型代碼之前的API像:

interface?Collection?{

public?boolean?containsAll(Collection c);

public?boolean?addAll(Collection c);

}

一個稚嫩的泛型化嘗試:

interface?Collection<E>?{

public?boolean?containsAll(Collection<E>?c);

public?boolean?addAll(Collection<E>?c);

}

這當然是類型安全的,但是它不支持這個API的原始契約(original contract)。

containsAll()?方法能對所有進來的任意類型的collection工作。它只有在傳進來的collection中真正只包含E的實例才成功,但是:

l?????????傳進來的collection的靜態類型可能不同,可能是因為調用者不知道傳進來的colleciton的精確類型,或者因為它是一個Collection<S>,S是E的子類型。

l?????????用一個不同類型的collection來調用containsAll()應該是合法的。這個例程應該能夠工作,返回false。

對addAll(),我們應該能夠添加任何元素是E的子類型的collection。我們已經在第5部分講述了怎么正確的處理這種情況。

?你還應該保證修訂過的API保持與老客戶端的二進制兼容。者以為者API的erasure必須與老的未泛型化版本一樣。在大多數情況下,這是很自然的結果,但是有些精巧的情形(subtle cases)。我們看看我們已經碰到過的精巧的情形中的一個(one of the subtle cases),方法Collections.max()。就像我們在第9部分看到的,一個似是而非的max()的方法簽名是:

public?static?<T?extends?Comparable<??super?T>>?T max(Collection<T>?coll)

這很好,除了擦除(erasure)后的簽名是:

public?static?Comparable max(Collection coll)

這和老版本的max()?的簽名不同:

public?static?Object max(Collection coll)

當然可以把max()定義為這個簽名,但是這沒有成為現實,因為所有調用了Collections.max()的老的二進制class文件依賴于返回Object的簽名。

我們可以強迫the erasure不同,通過給形式類型參數T顯式的定義一個父類。

public?static?<T?extends?Object & Comparable<??super?T>>?T max(Collection<T>?coll)

這是一個對一個類型參數給定多個界限(multiple bounds)的例子,是用語法?T1 & T2 … & Tn。一個有多個界限的類型的參數是所有界限中列出來的類型的子類。當多個界限被使用的時候,界限中的第一個類型被用作這個類型參數的erasure。

(原文:This is an example of giving multiple bounds for a type parameter, using the syntax T1& T2 ... &?Tn.?A type variable with multiple bounds is known to be a subtype of all of the types listed in the bound. When a multiple bound is used, the first type mentioned in the bound is used as the erasure of the type variable.)

最后,我們應該想到max只從傳進來的collection中讀取數據,因此它對元素是T的子類的collection可用。這給我們JDK中使用的真正的簽名:

public?static?<T?extends?Object & Comparable<??super?T>>?T max(Collection<??extends?T>?coll)

實際中出現那么棘手的問題是很罕見的,但是專業庫設計師應該準備好非常仔細的考慮轉換現存的API。

另一個需要小心的問題是協變式返回值(covariant returns),就是說在子類中獲得一個方法的返回值(refining the return type of a method in a subclass)。在老API中你無法使用這個特性帶來的好處。

為了知其原因,讓我們看一個例子。

假定你的原來的API是下面的形式:

public?class?Foo?{

public?Foo create(){...}

// Factory, should create an instance of whatever class it is declared in

}

public?class?Bar?extends?Foo?{

public?Foo create(){...}?// actually creates a Bar

}

為了使用協變式返回值的好處,你把它改成:

public?class?Foo?{

public?Foo create(){...}

// Factory, should create an instance of whatever class it is declared in

}

public?class?Bar?extends?Foo?{

public?Bar create(){...}?// actually creates a Bar

}

現在,假定你的一個第三方客戶代碼:

public?class?Baz?extends?Bar?{

public?Foo create(){...}?// actually creates a Baz

}

Java虛擬機并不直接支持不同類型返回值的方法重載。這個特性是由編譯器來支持的。因此,除非Baz類被重新編譯,它不會正確的重載Bar的create()方法,而且,Baz必須被修改,因為Baz的代碼被拒絕,它的create的返回值不是Bar中create返回值的子類。(原文:?Consequently, unless the class Baz is recompiled, it will not properly override the create() method of Bar.Furthermore, Baz will have to be modified, since the code will be rejected as written - the return type of create() in Baz is not a subtype of the return type of create() in Bar.)

(譯注:上面的一段話有些莫名其妙,我測試過這個例子,在jdk1.4下,三個類都編譯之后改變Bar,只在jdk5下重新編譯Bar,然后在jdk5下,Baz仍然能夠被使用,當然那,無法使用?Baz b = baz.create();這樣的代碼。)

11.致謝

Erik Ernst, Christian Plesner Hansen, Jeff Norton, Mads Torgersen, Peter von der Ah′e and Philip Wadler contributed material to this tutorial.

Thanks to David Biesack, Bruce Chapman, David Flanagan, Neal Gafter, ¨ Orjan Petersson,Scott?Seligman, Yoshiki Shibata and Kresten Krab Thorup for valuable feedback on earlier versions of this tutorial.?Apologies to anyone whom I’ve forgotten.

轉載于:https://www.cnblogs.com/zhaoyibing/p/9050527.html

總結

以上是生活随笔為你收集整理的JAVA泛型知识(一)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

91免费观看 | 亚洲国产视频a | 99视频在线看 | 不卡中文字幕av | 亚洲视频h | 一区二区精品在线观看 | 亚洲午夜av久久乱码 | 亚洲国产综合在线 | 日韩精品一区二区三区中文字幕 | 久草91视频 | 日日噜噜噜噜夜夜爽亚洲精品 | 国产成人亚洲在线观看 | 国产日韩中文在线 | 国产成人性色生活片 | 天天夜夜亚洲 | av福利电影 | 久久久久久久久久免费视频 | 日韩av在线一区二区 | 91麻豆精品国产91久久久更新时间 | 亚洲综合小说 | 在线播放视频一区 | 成人久久 | 色综合天天综合网国产成人网 | 久久国产精品99久久久久久老狼 | 操老逼免费视频 | 亚洲第二色 | 日韩精品视频在线免费观看 | 人人草人 | 韩日三级av | 麻豆91在线观看 | 国产v亚洲v | 性色av香蕉一区二区 | 国产免费片 | 日韩电影在线观看一区二区三区 | 少妇自拍av | 在线观看成人一级片 | 久久av网址 | 国产精品一区二区三区四 | 日韩乱色精品一区二区 | 91精品办公室少妇高潮对白 | 午夜 在线 | 久草在线 | 狠狠躁夜夜躁人人爽视频 | 国产在线97| av超碰在线观看 | 天天操操操操操 | 天天干,天天插 | 天天草天天干天天 | 在线观看91久久久久久 | 日日夜夜亚洲 | 欧美性免费 | 在线婷婷| 少妇av网 | 九九热在线视频 | 成人看片 | 日韩欧在线 | 中文免费观看 | 久久另类视频 | 中文字幕 国产视频 | 成人免费看片98欧美 | 中文字幕亚洲综合久久五月天色无吗'' | 日韩一区二区免费播放 | av在线免费网站 | 日本在线观看一区 | 亚洲综合色av | 国产免费亚洲高清 | 成人a毛片 | 91成人免费在线 | 精品国产伦一区二区三区观看说明 | 国产一区网 | 国产视频在线观看一区二区 | 成年人免费观看在线视频 | 黄色网www | 国产精品男女 | 色婷婷久久久综合中文字幕 | 欧美性护士 | 亚洲狠狠婷婷 | 国产视频久久久 | 日韩色综合网 | 国产高清视频色在线www | 不卡的av在线播放 | 国产精品成人自产拍在线观看 | 国产精品久久电影网 | 精品91视频 | 四虎在线免费观看视频 | 亚洲 欧美 日韩 综合 | 婷婷色伊人 | 免费h漫在线观看 | 在线探花| 狠狠躁日日躁狂躁夜夜躁 | 狠狠狠色丁香婷婷综合久久五月 | 日韩电影久久久 | 日日爱999| 精品伊人久久久 | 色中色综合 | 亚洲高清网站 | 在线观看中文字幕视频 | 天天干一干 | 日韩理论在线 | 黄色美女免费网站 | 美女免费黄视频网站 | 欧美日韩久 | 美女久久一区 | 欧洲一区二区三区精品 | 视频一区二区国产 | 日本精品在线 | 久久国产成人午夜av影院宅 | 国产精品久久久视频 | 久久精品视频免费播放 | 日韩在线观看你懂得 | 国产高清网站 | 亚洲第二色 | 国产综合精品一区二区三区 | 天天射网 | 国产网红在线观看 | 日韩高清国产精品 | 成人三级网站在线观看 | 日韩一级黄色大片 | 中文字幕 成人 | 日韩欧美高清在线 | www色片 | 美女免费黄视频网站 | 狠狠色婷婷丁香六月 | 人人干人人艹 | 91精品在线观看入口 | 99久久久久成人国产免费 | 中文字幕中文字幕在线中文字幕三区 | 天天干天天做 | 久久天堂精品视频 | 最近高清中文字幕在线国语5 | 最近中文国产在线视频 | 999抗病毒口服液 | 香蕉视频日本 | 人人爱夜夜操 | 国产精品系列在线播放 | 国产高h视频 | 久久久久久福利 | 三级黄色理论片 | 日韩免费中文字幕 | 久久99在线| 嫩嫩影院理论片 | 天天插综合 | 天天拍夜夜拍 | 免费观看十分钟 | 日韩丝袜 | 国产精品高潮在线观看 | 日本中文字幕在线视频 | 伊人开心激情 | 99 视频 高清| 麻豆一区二区三区视频 | 在线观看国产区 | 亚洲精品视 | 日韩成人xxxx | 日韩中文在线视频 | 国产福利中文字幕 | 99久久精品久久久久久动态片 | 国产精品日韩高清 | 三级av免费看 | 中文字幕日韩一区二区三区不卡 | 欧美日韩xxxxx| 欧美色图88 | 超碰.com| 黄色网在线播放 | 久久99精品国产 | 久久免费一级片 | 182午夜在线观看 | 日韩性片 | 五月天久久久 | 国产一级片毛片 | 亚洲精品中文字幕在线 | 国产视频亚洲视频 | 亚洲视频综合在线 | 在线观看视频中文字幕 | 日韩在线视频一区二区三区 | 国产美女视频 | 亚洲少妇天堂 | 亚洲婷婷免费 | av 一区二区三区四区 | 三级在线国产 | 免费a视频在线观看 | 亚洲三级在线 | 久久久久一区二区三区 | 亚洲黄色软件 | 欧美一级性生活 | 日韩资源在线 | 婷婷午夜天 | 天天干天天搞天天射 | 亚洲伦理一区 | av专区在线 | 日韩高清国产精品 | 懂色av一区二区在线播放 | 精品视频久久 | 国产激情小视频在线观看 | 精品女同一区二区三区在线观看 | 四虎成人精品永久免费av | 亚洲综合成人婷婷小说 | 中文字幕在线视频精品 | 日韩综合一区二区三区 | 精品国产1区| 精品视频在线视频 | 成年人在线免费看片 | 怡红院av久久久久久久 | 亚洲精品乱码久久久久久 | www蜜桃视频 | 午夜精品剧场 | 91视频大全 | 国产精品嫩草69影院 | 国产精品成人国产乱 | 精品亚洲免a | 一区二区电影在线观看 | 中文字幕日本电影 | 五月天综合激情 | 亚洲精品字幕在线 | 日韩在线高清免费视频 | 国产美女无遮挡永久免费 | 国精产品999国精产品视频 | 色综合天天爱 | 毛片美女网站 | 欧美日韩国产一二三区 | 欧美精品二区 | 亚洲一区视频在线播放 | 天天干,天天射,天天操,天天摸 | 久久av中文字幕片 | 日韩精品亚洲专区在线观看 | 久草视频免费观 | av成人免费观看 | 国产高清视频在线免费观看 | 五月天天天操 | 免费成人在线视频网站 | 国产高清免费在线观看 | 亚洲国产精品一区二区久久hs | 爱av在线网 | 国产成人精品不卡 | 在线成人短视频 | 国色天香在线观看 | 黄色片软件网站 | 久操视频在线播放 | 在线蜜桃视频 | 久久亚洲欧美日韩精品专区 | 99色在线视频 | 国产成人福利在线观看 | 91麻豆传媒 | 欧美亚洲成人免费 | 九九久久精品 | 亚洲最新av | 午夜久久 | 在线国产高清 | 麻豆视频免费看 | 精品黄色在线观看 | 91粉色视频 | 欧洲成人av | 黄色在线成人 | 99久热在线精品视频观看 | 天天搞天天干天天色 | 亚洲男男gⅴgay双龙 | 日韩中文字幕免费电影 | 日韩在线免费小视频 | 日日碰狠狠躁久久躁综合网 | 伊人资源视频在线 | 久久免费美女视频 | 午夜a区| 综合色亚洲 | 国模精品在线 | 久久伊人色综合 | 国产 中文 日韩 欧美 | 久久久观看 | 国产在线视频一区 | 在线观看日韩中文字幕 | 黄色片免费电影 | 久久成人国产精品 | 日韩欧美在线综合网 | 欧美日韩亚洲在线 | 中文字幕在线成人 | 国产在线欧美在线 | 欧美成人在线免费观看 | 国产精品 日韩 | 国产精品久久久久久久久久久久 | www.色午夜,com | 四虎最新域名 | 国产精品一区二区久久久久 | 国产精品视频999 | 国产精品99久久久久久武松影视 | 99精品久久精品一区二区 | 日本一区二区三区视频在线播放 | 国产精品自产拍在线观看中文 | 成人免费在线网 | 日韩精品一区二区免费 | 久久精品伊人 | 大胆欧美gogo免费视频一二区 | 人人添人人 | 精品国产色 | 国产午夜精品一区二区三区在线观看 | 四虎影视成人永久免费观看视频 | 麻豆传媒视频在线播放 | 黄色在线视频网址 | 国产成人精品一区二区在线观看 | 国产精品国产三级国产不产一地 | 色资源二区在线视频 | 一区二区三区视频网站 | 亚洲精品在线视频观看 | 国产日韩欧美在线播放 | 国产又粗又硬又爽的视频 | 欧美成人一区二区 | 日韩在线观看视频网站 | 色婷婷综合久色 | av中文字幕日韩 | 色综合五月天 | 国产一区二区午夜 | 狠狠色丁香婷婷综合橹88 | 国产专区在线看 | 久草色在线观看 | 粉嫩高清一区二区三区 | 狠狠色丁香婷婷综合久小说久 | 亚洲日本在线视频观看 | 久久综合久久综合久久综合 | 国际精品久久久 | 91精品视频免费在线观看 | 在线观看的黄色 | 2023年中文无字幕文字 | 97超碰福利久久精品 | 中文字幕观看在线 | 中文字幕在线字幕中文 | 久草免费在线观看视频 | 中文字幕影片免费在线观看 | 91成人精品一区在线播放 | 国产视频美女 | av电影免费在线 | 国产小视频福利在线 | 麻豆视频免费入口 | 91久久国产精品 | 91视频观看免费 | 色综合网在线 | 久久国产精品二国产精品中国洋人 | 国产成人精品福利 | 精品福利视频在线观看 | 精品视频免费久久久看 | 亚洲成人免费在线观看 | 中文字幕在线久一本久 | 亚洲欧美成aⅴ人在线观看 四虎在线观看 | 亚洲国产成人精品在线观看 | 亚洲aⅴ乱码精品成人区 | 91丨九色丨蝌蚪丨对白 | 久久精品国产亚洲aⅴ | 亚洲情婷婷 | 免费在线观看国产精品 | 曰本免费av | 久久久免费网站 | 五月激情电影 | 国产一区二区综合 | 国产精品久久在线观看 | 国产成人三级一区二区在线观看一 | 国产福利午夜 | 久久五月情影视 | 久久综合久久八八 | 色综合久久综合 | 日本性久久 | 久久韩国免费视频 | 一区二区三区在线观看免费视频 | 欧美va在线观看 | 国产一级片免费观看 | 国产精品久久久久久久久久东京 | 少妇精69xxtheporn | 日日碰狠狠添天天爽超碰97久久 | 91完整版在线观看 | 亚洲视频 一区 | 色欧美成人精品a∨在线观看 | 视频成人免费 | 国产亚洲婷婷 | 91av观看| 久久影院精品 | 欧美日韩国产页 | 久久不卡视频 | 在线播放视频一区 | 久久露脸国产精品 | wwwav视频| 四虎影视成人精品国库在线观看 | 成人免费视频在线观看 | 婷婷久久丁香 | 婷婷久月| 日本精品一区二区 | 国内精品久久影院 | 97在线看 | 国产在线播放观看 | av日韩不卡 | 免费在线观看的av网站 | 国产精品久久久久久模特 | 国产综合精品一区二区三区 | 干干日日 | 精品亚洲成a人在线观看 | 精品久久久久久亚洲综合网站 | 欧美俄罗斯性视频 | 日韩欧美精品在线观看视频 | 91伊人久久大香线蕉蜜芽人口 | 精品亚洲一区二区三区 | 国产黄色高清 | 午夜电影 电影 | 字幕网在线观看 | 久久久久免费电影 | 国产中文字幕在线免费观看 | 九九热在线免费观看 | 国产韩国精品一区二区三区 | 国产在线日韩 | 日韩激情网 | 婷婷久月 | 日韩婷婷 | 免费中午字幕无吗 | 二区精品视频 | 在线免费观看黄色小说 | 国内久久久久 | 久久艹在线 | 美女视频黄是免费的 | 国产精品久久久久一区二区国产 | 日日夜夜亚洲 | 人人爱爱| 69av久久| 日韩特黄一级欧美毛片特黄 | 日韩精品免费一线在线观看 | 中文国产字幕在线观看 | 人人艹人人 | av免费在线观 | 欧美一级片播放 | 97网站 | 亚洲精品xx | 久久久久久久综合色一本 | 精品久久综合 | 色综合天天狠天天透天天伊人 | 亚洲激情国产精品 | 成人在线播放网站 | 欧美日韩另类在线观看 | 国产精品欧美久久久久久 | 玖玖视频在线 | 中国一级片在线 | 久久在线 | 夜夜夜夜爽 | 国产日本在线观看 | 麻豆播放 | 国产在线久久久 | 久久曰视频 | 日韩久久久久久久久久久久 | 爱射综合 | 欧美一区二区三区在线 | 在线观看中文字幕av | 美女视频永久黄网站免费观看国产 | 亚洲三级在线免费观看 | 一区二区精 | 久久人人97超碰精品888 | 婷婷九月激情 | 亚洲视频大全 | 日韩精品电影在线播放 | 亚洲人成在线观看 | 91九色在线观看视频 | 久久精品女人毛片国产 | 久久深夜 | 免费特级黄色片 | 99精品国产99久久久久久福利 | 美女视频黄免费的久久 | 欧美一级看片 | 黄色小说在线免费观看 | 91精品高清| 亚欧日韩成人h片 | 国产一级在线看 | 久久福利综合 | 国产亚洲在 | 狠狠狠狠狠色综合 | 欧美男女爱爱视频 | 国产69精品久久久久久 | 久久综合免费 | 香蕉在线视频播放网站 | 久久这里精品视频 | 九七视频在线 | 亚洲精品视频在线免费 | 日日夜夜网 | 天天操狠狠干 | 中文字幕亚洲精品日韩 | 国产精品毛片完整版 | 国产精品久久久久久婷婷天堂 | aaaaaa毛片| 色老板在线 | av成人在线播放 | 日韩精品播放 | 成人在线免费av | 超碰97成人| 九九在线视频 | 91激情视频在线观看 | 亚洲综合视频在线 | 日韩成人av在线 | 精品国产午夜 | 久久激情久久 | 亚洲一级二级三级 | 91麻豆传媒 | 亚洲国产日韩一区 | 天天曰天天 | 日本动漫做毛片一区二区 | 久久五月激情 | 国产精品高潮呻吟久久av无 | 国产一区欧美一区 | 午夜视频在线观看网站 | 亚洲va综合va国产va中文 | 午夜 久久 tv | 麻豆免费在线播放 | 久久99国产精品自在自在app | 探花视频免费在线观看 | 香蕉日日 | 久久久久国产成人精品亚洲午夜 | 欧美精品在线观看免费 | 五月天国产 | 亚洲精品国产综合99久久夜夜嗨 | 久久艹精品 | 黄色亚洲大片免费在线观看 | 丁香在线观看完整电影视频 | 91看片看淫黄大片 | 99久久精品国产一区二区三区 | 天天添夜夜操 | 免费看污在线观看 | 亚洲精品视频免费观看 | 国产精品久久久久久久免费大片 | 国产精品网红福利 | 亚洲美女免费视频 | 国产精品久久婷婷六月丁香 | 欧美va天堂va视频va在线 | 日韩美女久久 | 亚洲天堂网视频在线观看 | 草在线视频 | 免费高清影视 | 婷婷五天天在线视频 | 亚洲精品乱码久久久久v最新版 | 亚洲成av人影片在线观看 | 91一区啪爱嗯打偷拍欧美 | 99精品在线 | 亚洲日本精品 | 国产成人免费在线 | 日日日干 | www.伊人色.com | 中文在线亚洲 | 亚洲成人av电影在线 | 精品v亚洲v欧美v高清v | 亚洲综合在线五月天 | 四虎影视成人精品 | 欧美一区二区三区免费观看 | 波多野结衣精品在线 | 天天操天天射天天爱 | 九九视频热 | 亚洲精品动漫久久久久 | 欧美日韩一区二区久久 | 国产码电影 | 91精品办公室少妇高潮对白 | av福利网址导航 | 国产91探花| av女优中文字幕在线观看 | 伊人手机在线 | 久久精品在线 | 婷婷色综合网 | 国产精品福利在线播放 | 五月色丁香 | 久草在线中文视频 | 欧美性超爽| 综合激情网... | 欧美在线观看视频免费 | 亚洲欧美视频在线 | 国产精品美女久久久免费 | 精品亚洲男同gayvideo网站 | 五月综合色婷婷 | 欧美一级视频免费看 | 91手机电影 | 亚洲国产精品激情在线观看 | 国产成人精品一区一区一区 | 色婷婷av一区二 | 深夜免费小视频 | 精品国产一区二区三区在线 | 精品中文字幕在线 | 日日精品| 国产三级视频 | 国产日韩欧美在线免费观看 | 中文字幕在线免费观看视频 | 国产99在线免费 | 国产日韩中文字幕在线 | 亚洲国产精品免费 | 欧美aa一级 | 久久成人黄色 | 日韩免费观看高清 | 免费国产在线观看 | 中文字幕综合在线 | 亚洲 欧美 日韩 综合 | www免费视频com | 久久一精品 | 亚洲精品五月 | 亚洲干视频在线观看 | 成人三级网站在线观看 | 国产一区福利 | 日本天天色 | 人人澡视频 | 天天草天天干天天射 | 黄色免费观看网址 | 成人免费观看网址 | 日韩欧美精品在线视频 | 色瓜| 欧美一区二区三区四区夜夜大片 | 香蕉视频在线免费 | 国产精品s色 | 成人午夜在线电影 | 91亚洲精品在线观看 | 国产精品九九九 | 国产精品视频地址 | 色开心 | 亚洲一区天堂 | 天天色视频 | 久久综合婷婷国产二区高清 | 一区二区视频播放 | 国产精品一区二区免费在线观看 | www.99久久.com| 亚洲人毛片 | 中文字幕在线观看一区 | 98久9在线 | 免费 | 亚洲伊人成综合网 | 亚洲欧洲精品一区二区精品久久久 | 国产精品一区二区久久精品爱微奶 | 国产永久免费 | 成年人在线免费看片 | 亚洲精品白浆高清久久久久久 | 在线99热 | 免费看久久久 | 久久精品久久久精品美女 | 天天插天天狠 | 免费特级黄毛片 | 制服丝袜亚洲 | 久久色视频| 色姑娘综合网 | 最新99热 | 精品久久久影院 | 欧美极品少妇xxxxⅹ欧美极品少妇xxxx亚洲精品 | 在线播放第一页 | 超碰成人网 | 日韩精品极品视频 | 国产又粗又猛又爽 | 又爽又黄在线观看 | www.狠狠色.com | 午夜精品一区二区三区可下载 | 欧美精品久 | 天天操天天操天天操天天操 | adn—256中文在线观看 | 午夜av在线播放 | 国产精品免费一区二区三区在线观看 | 黄色精品一区二区 | 免费中午字幕无吗 | 婷婷丁香久久五月婷婷 | 国产香蕉视频在线观看 | 国产一区欧美二区 | 天堂麻豆 | 国产精品国产三级国产aⅴ无密码 | 夜夜高潮夜夜爽国产伦精品 | 久久精品99国产精品酒店日本 | 日韩免费在线观看网站 | 玖玖视频网 | 成年人在线免费视频观看 | 在线成人高清电影 | 久久精品国产亚洲aⅴ | 一区二区三区四区五区在线 | 日韩黄在线观看 | 国产香蕉视频在线播放 | 免费三级骚 | 尤物97国产精品久久精品国产 | 日日日爽爽爽 | 夜夜操网 | 四虎影视成人永久免费观看视频 | 中文在线www| 国产精品毛片久久久久久久久久99999999 | 日本黄色大片免费看 | 欧美激情综合色综合啪啪五月 | 久久精品毛片 | 亚洲欧美日韩在线一区二区 | 啪啪免费视频网站 | 99久久精品国产免费看不卡 | 国产精品igao视频网网址 | 热热热热热色 | 久草视频在线免费 | 国产亚洲欧美精品久久久久久 | 精品国产诱惑 | 日韩在线观看中文 | 国产一二三精品 | 久草电影免费在线观看 | 亚洲专区一二三 | 国产一区二区手机在线观看 | 亚洲第一中文网 | 日韩a在线观看 | 国产流白浆高潮在线观看 | 国产免费一区二区三区网站免费 | 91精品办公室少妇高潮对白 | av电影免费在线看 | 色综合天天狠天天透天天伊人 | 精品久久久久亚洲 | 国产精品18久久久久白浆 | 免费在线观看a v | 国产精品一区久久久久 | 一区二区三区国产欧美 | 久久久久在线 | 免费精品人在线二线三线 | 正在播放 国产精品 | 九色91av| 日韩高清一二区 | 中文字幕国语官网在线视频 | 免费看的黄色片 | 国产精品美女久久久久久久久 | 国产xxxxx在线观看 | 午夜三级大片 | 婷婷丁香六月 | 久久99久久99精品免视看婷婷 | 国产精品久久久久一区二区三区共 | 欧美精品免费一区二区 | 日韩免费二区 | 免费在线观看污网站 | 91精品国产麻豆 | 亚洲精品日韩一区二区电影 | 精品一区二区在线播放 | 久草在线免费电影 | 特级毛片网| 亚洲人成网站精品片在线观看 | 中文字幕在线色 | 免费看色视频 | av丝袜在线| 九九九热精品免费视频观看 | 欧美性色综合网 | 午夜美女福利 | 91精品蜜桃| 亚洲成人家庭影院 | www国产亚洲精品久久网站 | 日韩一区二区免费播放 | 毛片网在线 | 美女视频一区二区 | 国内精品久久久久影院优 | 成人久久18免费网站图片 | 在线观看你懂的网址 | 欧美一级片免费在线观看 | 国产精品6999成人免费视频 | 深爱五月网 | 91视频91自拍 | a√资源在线 | 日韩在线三区 | 国产精品国产自产拍高清av | www免费视频com| 在线观看视频你懂 | www欧美xxxx| 美女视频是黄的免费观看 | 国产欧美精品一区二区三区四区 | 97视频在线免费观看 | 国产香蕉97碰碰碰视频在线观看 | 亚洲一区二区三区在线看 | 久久精品第一页 | 久久老司机精品视频 | 黄色av电影| 国模视频一区二区 | 91精品国产麻豆 | 日韩二区在线播放 | 欧美尹人 | 999视频网| 久久成人麻豆午夜电影 | 香蕉视频导航 | 91九色pron| 欧美一区,二区 | 日日干激情五月 | 日韩av不卡在线播放 | 久久免费av电影 | 欧美日韩国产一区二 | 亚洲精品一区二区三区在线观看 | 午夜精品999 | 一级免费观看 | 久草精品视频 | 久久成年人 | 亚洲精品高清在线 | 国产日韩中文在线 | 国产无限资源在线观看 | 在线观看免费成人av | 色偷偷888欧美精品久久久 | 毛片网站在线看 | 精品久久久网 | 日韩精品无码一区二区三区 | 在线不卡中文字幕播放 | 美女久久99| 99久热在线精品视频观看 | 精品av在线播放 | 久久伊人国产精品 | 夜夜操狠狠操 | 99 色 | 日韩视频a| 国产在线观看91 | 在线观看免费 | 很黄很污的视频网站 | 国产美腿白丝袜足在线av | 五月天六月丁香 | 久久久在线视频 | 婷婷激情五月 | 西西44人体做爰大胆视频 | 久久久久久久av麻豆果冻 | 免费av小说 | 国产一二三在线视频 | av线上看 | 2024av| 日韩小视频网站 | 亚洲 欧美日韩 国产 中文 | 欧美激情片在线观看 | 中文字幕在线观看1 | 亚洲少妇久久 | 婷婷中文字幕在线观看 | 国产精品一区二区三区观看 | 欧美在线观看禁18 | 视频一区二区视频 | 伊人视频| 亚州精品在线视频 | 一区二区三区免费网站 | 久久综合亚洲鲁鲁五月久久 | 精品国产一区二区三区在线 | 亚洲激情免费 | 久久最新视频 | 欧美 亚洲 另类 激情 另类 | 日韩欧美在线观看一区二区三区 | 日韩av免费观看网站 | 国产精品福利无圣光在线一区 | 日韩在线观看影院 | 美国av片在线观看 | 狠狠色丁香久久婷婷综 | 亚洲视频久久久久 | 国产高清在线观看av | 午夜12点| 国产黄色片免费在线观看 | 色网站黄| 久久免费的精品国产v∧ | 国产97碰免费视频 | 人人干网 | 91精品国产一区二区在线观看 | 人人爱天天操 | 国产精品色 | 91丨九色丨国产在线 | 国产成人精品在线播放 | 国产午夜免费视频 | 中文字幕av全部资源www中文字幕在线观看 | 日韩av成人免费看 | 夜夜夜影院 | 久久精品中文字幕 | 国产精品18久久久久久首页狼 | 日日干干 | 亚洲一区 av | 日韩av中文字幕在线 | www日韩在线观看 | 日本精油按摩3 | 亚a在线 | 91精品免费看 | 国产一区精品在线观看 | 91专区在线观看 | 久要激情网 | 欧美va日韩va| 亚洲色图美腿丝袜 | 99热在线看| 西西www444 | www.久久成人 | 日韩在线观看一区二区三区 | 99久视频 | 精品久久久久一区二区国产 | 91理论电影| 粉嫩高清一区二区三区 | 高清av网| 亚洲一区视频免费观看 | 亚洲精品久久久蜜桃 | 久久99久久久久久 | 日韩一二区在线观看 | 国产97av| 免费看成人av| 免费视频黄| 国产亚洲日| 九色自拍视频 | 人人讲下载 | 美女黄网久久 | 777久久久 | 97电影院网 | 久久免费视频国产 | 国产精品18久久久久久vr | 日日夜夜精品网站 | 又黄又爽又刺激视频 | 久久欧美视频 | 中文字幕在线网 | japanese黑人亚洲人4k | 91精品老司机久久一区啪 | 九九在线免费视频 | 97天堂网 | 国产精品久久久久久久久久 | 99免费在线播放99久久免费 | 国产精品一区二区 91 | 精品一区二区久久久久久久网站 | 久久高清| 久久精品久久久久电影 | 日韩精品一区二区久久 | 国产精品麻豆欧美日韩ww | 天天操狠狠干 | 国产精品9999久久久久仙踪林 | 狠狠躁夜夜躁人人爽超碰97香蕉 | 欧美精品一区二区三区四区在线 | 伊香蕉大综综综合久久啪 | 精品在线观看一区二区 | 精品国产乱码久久久久久1区二区 | 热久久国产精品 | 欧洲精品二区 | 91porny九色在线播放 | 久久精品免费看 | 精品国产乱码一区二 | 国产美女精品在线 | 九九免费在线视频 | 日本午夜在线亚洲.国产 | 午夜电影一区 | 久青草视频在线观看 | 操操操人人| av网站在线观看免费 | 精品久久久久久综合 | 国产精品wwwwww | 操操操日日 | 亚洲精品国产精品国自产在线 | 在线一区观看 | 中文字幕在线资源 | 日韩免费一区 | 国产精品v欧美精品 | 蜜桃av人人夜夜澡人人爽 | 97色噜噜 | 深夜免费福利网站 | 国产免费国产 | 日本精品久久久一区二区三区 | 97视频在线播放 | 特级西西444www大胆高清无视频 | 麻豆 91 在线| 欧美一级片免费观看 | 综合色狠狠 | 日韩欧美视频一区 | 国产视频1区2区3区 久久夜视频 | 狠狠色狠狠色合久久伊人 | 国产在线免费观看 | 精品国产一二三 | 国产高清无线码2021 | 97电院网手机版 | 精品国产a | 精品在线视频一区 | 国产中的精品av小宝探花 | 国产看片网站 | 日韩久久一区二区 | 五月综合在线观看 | 深夜福利视频在线观看 | 亚洲婷婷在线视频 | 久草在线视频首页 | 国产福利不卡视频 | 亚洲精品乱码 | 99精品国产在热久久 | 国产a精品 | 久久国产午夜精品理论片最新版本 | 国产视频高清 | 极品嫩模被强到高潮呻吟91 | 婷婷在线免费观看 | 视频在线一区二区三区 | 久久免费视频在线观看30 | 久久国精品 | 中文字幕av影院 | 香蕉在线观看视频 | 国产精品久久中文字幕 | 久久这里只有精品久久 | 婷婷激情影院 | 韩日精品在线观看 | 性色av一区二区三区在线观看 | 亚洲夜夜网 | 欧美孕妇与黑人孕交 | 黄色a一级视频 | 久久精品女人毛片国产 | 国内久久视频 | 四虎影视精品永久在线观看 | 久草在线免费播放 | 伊人网av| 超级碰视频 | 欧美亚洲免费在线一区 | 色网址99| 亚洲精品大全 | 99视频偷窥在线精品国自产拍 | 1024手机基地在线观看 | 色网免费观看 | 毛片888| 五月婷网站 | 夜夜夜夜夜夜操 | 顶级bbw搡bbbb搡bbbb | 91麻豆精品国产91久久久久久 | 免费网站色 | 91在线资源 | 国产视频首页 | 国产精品毛片一区二区三区 | 91人人爽久久涩噜噜噜 | 91免费网站在线观看 | 五月天婷亚洲天综合网鲁鲁鲁 | 久久综合狠狠综合 | 国产精品va在线观看入 | 丝袜一区在线 | 日韩高清不卡一区二区三区 | 国产精品午夜在线 | 国产精品国内免费一区二区三区 | 在线之家免费在线观看电影 | 24小时日本在线www免费的 | 国内外成人免费在线视频 | 欧美福利视频一区 |