青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

posts - 195,  comments - 30,  trackbacks - 0

Java 語言的一個優(yōu)點(diǎn)就是取消了指針的概念,但也導(dǎo)致了許多程序員在編程中常常忽略了對象與引用的區(qū)別,本文會試圖澄清這一概念。并且由于Java不能通過簡單 的賦值來解決對象復(fù)制的問題,在開發(fā)過程中,也常常要要應(yīng)用clone()方法來復(fù)制對象。本文會讓你了解什么是影子clone與深度clone,認(rèn)識它 們的區(qū)別、優(yōu)點(diǎn)及缺點(diǎn)。
看到這個標(biāo)題,是不是有點(diǎn)困惑:Java語言明確說明取消了指針,因?yàn)橹羔樛窃趲矸奖愕耐瑫r也是導(dǎo)致代碼不安全的根源,同時也會使程序的變得非常復(fù) 雜難以理解,濫用指針寫成的代碼不亞于使用早已臭名昭著的"GOTO"語句。Java放棄指針的概念絕對是極其明智的。但這只是在Java語言中沒有明確 的指針定義,實(shí)質(zhì)上每一個new語句返回的都是一個指針的引用,只不過在大多時候Java中不用關(guān)心如何操作這個"指針",更不用象在操作C++的指針那 樣膽戰(zhàn)心驚。唯一要多多關(guān)心的是在給函數(shù)傳遞對象的時候。如下例程:

package reference;
class Obj{
String str = "init value";
public String toString(){
return str;
}
}
public class ObjRef{
Obj aObj = new Obj();
int aInt = 11;
public void changeObj(Obj inObj){
inObj.str = "changed value";
}
public void changePri(int inInt){
inInt = 22;
}
public static void main(String[] args)
{
ObjRef oRef = new ObjRef();

System.out.println("Before call changeObj() method: " + oRef.aObj);
oRef.changeObj(oRef.aObj);
System.out.println("After call changeObj() method: " + oRef.aObj);

System.out.println("==================Print Primtive=================");
System.out.println("Before call changePri() method: " + oRef.aInt);
oRef.changePri(oRef.aInt);
System.out.println("After call changePri() method: " + oRef.aInt);

}
}

/* RUN RESULT
Before call changeObj() method: init value
After call changeObj() method: changed value
==================Print Primtive=================
Before call changePri() method: 11
After call changePri() method: 11

*
*/


這段代碼的主要部分調(diào)用了兩個很相近的方法,changeObj()和changePri()。唯一不同的是它們一個把對象作為輸入?yún)?shù),另一個把 Java中的基本類型int作為輸入?yún)?shù)。并且在這兩個函數(shù)體內(nèi)部都對輸入的參數(shù)進(jìn)行了改動。看似一樣的方法,程序輸出的結(jié)果卻不太一樣。 changeObj()方法真正的把輸入的參數(shù)改變了,而changePri()方法對輸入的參數(shù)沒有任何的改變。

從這個例子知道Java對對象和基本的數(shù)據(jù)類型的處理是不一樣的。和C語言一樣,當(dāng)把Java的基本數(shù)據(jù)類型(如int,char,double等)作為 入口參數(shù)傳給函數(shù)體的時候,傳入的參數(shù)在函數(shù)體內(nèi)部變成了局部變量,這個局部變量是輸入?yún)?shù)的一個拷貝,所有的函數(shù)體內(nèi)部的操作都是針對這個拷貝的操作, 函數(shù)執(zhí)行結(jié)束后,這個局部變量也就完成了它的使命,它影響不到作為輸入?yún)?shù)的變量。這種方式的參數(shù)傳遞被稱為"值傳遞"。而在Java中用對象的作為入口 參數(shù)的傳遞則缺省為"引用傳遞",也就是說僅僅傳遞了對象的一個"引用",這個"引用"的概念同C語言中的指針引用是一樣的。當(dāng)函數(shù)體內(nèi)部對輸入變量改變 時,實(shí)質(zhì)上就是在對這個對象的直接操作。

除了在函數(shù)傳值的時候是"引用傳遞",在任何用"="向?qū)ο笞兞抠x值的時候都是"引用傳遞"。如:

package reference;
class PassObj
{
String str = "init value";
}
public class ObjPassvalue
{

public static void main(String[] args)
{
PassObj objA = new PassObj();
PassObj objB = objA;

objA.str = "changed in objA";
System.out.println("Print objB.str value: " + objB.str); 
 

 
 

 
 

 
 
2 JAVA中的指針,引用及對象的clone 

 }
}
/* RUN RESULT
Print objB.str value: changed in objA
*/

第一句是在內(nèi)存中生成一個新的PassObj對象,然后把這個PassObj的引用賦給變量objA,第二句是把PassObj對象的引用又賦給了變量 objB。此時objA和objB是兩個完全一致的變量,以后任何對objA的改變都等同于對objB的改變。

即使明白了Java語言中的"指針"概念也許還會不經(jīng)意間犯下面的錯誤。

Hashtable真的能存儲對象嗎?

看一看下面的很簡單的代碼,先是聲明了一個Hashtable和StringBuffer對象,然后分四次把StriingBuffer對象放入到 Hashtable表中,在每次放入之前都對這個StringBuffer對象append()了一些新的字符串:

package reference;
import java.util.*;
public class HashtableAdd{
public static void main(String[] args){
Hashtable ht = new Hashtable();
StringBuffer sb = new StringBuffer();
sb.append("abc,");
ht.put("1",sb);
sb.append("def,");
ht.put("2",sb);
sb.append("mno,");
ht.put("3",sb);
sb.append("xyz.");
ht.put("4",sb);

int numObj=0;
Enumeration it = ht.elements();
while(it.hasMoreElements()){
System.out.print("get StringBufffer "+(++numObj)+" from Hashtable: ");
System.out.println(it.nextElement());
}
}
}

如果你認(rèn)為輸出的結(jié)果是:
get StringBufffer 1 from Hashtable: abc,
get StringBufffer 2 from Hashtable: abc,def,
get StringBufffer 3 from Hashtable: abc,def,mno,
get StringBufffer 4 from Hashtable: abc,def,mno,xyz.

那么你就要回過頭再仔細(xì)看一看上一個問題了,把對象時作為入口參數(shù)傳給函數(shù),實(shí)質(zhì)上是傳遞了對象的引用,向Hashtable傳遞 StringBuffer對象也是只傳遞了這個StringBuffer對象的引用!每一次向Hashtable表中put一次 StringBuffer,并沒有生成新的StringBuffer對象,只是在Hashtable表中又放入了一個指向同一StringBuffer對 象的引用而已。

對Hashtable表存儲的任何一個StringBuffer對象(更確切的說應(yīng)該是對象的引用)的改動,實(shí)際上都是對同一 個"StringBuffer"的改動。所以Hashtable并不能真正存儲能對象,而只能存儲對象的引用。也應(yīng)該知道這條原則對與Hashtable 相似的Vector, List, Map, Set等都是一樣的。

上面的例程的實(shí)際輸出的結(jié)果是:

/* RUN RESULT
get StringBufffer 1 from Hashtable: abc,def,mno,xyz.
get StringBufffer 2 from Hashtable: abc,def,mno,xyz.
get StringBufffer 3 from Hashtable: abc,def,mno,xyz.
get StringBufffer 4 from Hashtable: abc,def,mno,xyz.
*/

類,對象與引用

Java最基本的概念就是類,類包括函數(shù)和變量。如果想要應(yīng)用類,就要把類生成對象,這個過程被稱作"類的實(shí)例化"。有幾種方法把類實(shí)例化成對象,最常用 的就是用"new"操作符。類實(shí)例化成對象后,就意味著要在內(nèi)存中占據(jù)一塊空間存放實(shí)例。想要對這塊空間操作就要應(yīng)用到對象的引用。引用在Java語言中 的體現(xiàn)就是變量,而變量的類型就是這個引用的對象。雖然在語法上可以在生成一個對象后直接調(diào)用該對象的函數(shù)或變量,如:

new String("Hello NDP")).substring(0,3)  //RETURN RESULT: Hel

但由于沒有相應(yīng)的引用,對這個對象的使用也只能局限這條語句中了。

產(chǎn)生:引用總是在把對象作參數(shù)"傳遞"的過程中自動發(fā)生,不需要人為的產(chǎn)生,也不能人為的控制引用的產(chǎn)生。這個傳遞包括把對象作為函數(shù)的入口參數(shù)的情況,也包括用"="進(jìn)行對象賦值的時候。
范圍:只有局部的引用,沒有局部的對象。引用在Java語言的體現(xiàn)就是變量,而變量在Java語言中是有范圍的,可以是局部的,也可以是全局的。
生存期:程序只能控制引用的生存周期。對象的生存期是由Java控制。用"new Object()"語句生成一個新的對象,是在計算機(jī)的內(nèi)存中聲明一塊區(qū)域存儲對象,只有Java的垃圾收集器才能決定在適當(dāng)?shù)臅r候回收對象占用的內(nèi)存。 
 

 
 

 
 

 
--------------------------------------------------------------------------------
 
3 JAVA中的指針,引用及對象的clone 

 沒有辦法阻止對引用的改動。
什么是"clone"?

在實(shí)際編程過程中,我們常常要遇到這種情況:有一個對象A,在某一時刻A中已經(jīng)包含了一些有效值,此時可能會需要一個和A完全相同新對象B,并且此后對B 任何改動都不會影響到A中的值,也就是說,A與B是兩個獨(dú)立的對象,但B的初始值是由A對象確定的。在Java語言中,用簡單的賦值語句是不能滿足這種需 求的。要滿足這種需求雖然有很多途徑,但實(shí)現(xiàn)clone()方法是其中最簡單,也是最高效的手段。

Java的所有類都默認(rèn)繼承java.lang.Object類,在java.lang.Object類中有一個方法clone()。JDK API的說明文檔解釋這個方法將返回Object對象的一個拷貝。要說明的有兩點(diǎn):一是拷貝對象返回的是一個新對象,而不是一個引用。二是拷貝對象與用 new操作符返回的新對象的區(qū)別就是這個拷貝已經(jīng)包含了一些原來對象的信息,而不是對象的初始信息。

怎樣應(yīng)用clone()方法?

一個很典型的調(diào)用clone()代碼如下:

class CloneClass implements Cloneable{
public int aInt;
public Object clone(){
CloneClass o = null;
try{
o = (CloneClass)super.clone();
}catch(CloneNotSupportedException e){
e.printStackTrace();
}
return o;
}

有三個值得注意的地方,一是希望能實(shí)現(xiàn)clone功能的CloneClass類實(shí)現(xiàn)了Cloneable接口,這個接口屬于java.lang 包,java.lang包已經(jīng)被缺省的導(dǎo)入類中,所以不需要寫成java.lang.Cloneable。另一個值得請注意的是重載了clone()方 法。最后在clone()方法中調(diào)用了super.clone(),這也意味著無論clone類的繼承結(jié)構(gòu)是什么樣的,super.clone()直接或 間接調(diào)用了java.lang.Object類的clone()方法。下面再詳細(xì)的解釋一下這幾點(diǎn)。

應(yīng)該說第三點(diǎn)是最重要的,仔細(xì)觀察一下Object類的clone()一個native方法,native方法的效率一般來說都是遠(yuǎn)高于java中的非 native方法。這也解釋了為什么要用Object中clone()方法而不是先new一個類,然后把原始對象中的信息賦到新對象中,雖然這也實(shí)現(xiàn)了 clone功能。對于第二點(diǎn),也要觀察Object類中的clone()還是一個protected屬性的方法。這也意味著如果要應(yīng)用clone()方 法,必須繼承Object類,在Java中所有的類是缺省繼承Object類的,也就不用關(guān)心這點(diǎn)了。然后重載clone()方法。還有一點(diǎn)要考慮的是為 了讓其它類能調(diào)用這個clone類的clone()方法,重載之后要把clone()方法的屬性設(shè)置為public。

那么clone類為什么還要實(shí)現(xiàn)Cloneable接口呢?稍微注意一下,Cloneable接口是不包含任何方法的!其實(shí)這個接口僅僅是一個標(biāo)志,而且 這個標(biāo)志也僅僅是針對Object類中clone()方法的,如果clone類沒有實(shí)現(xiàn)Cloneable接口,并調(diào)用了Object的clone()方 法(也就是調(diào)用了super.Clone()方法),那么Object的clone()方法就會拋出 CloneNotSupportedException異常。

以上是clone的最基本的步驟,想要完成一個成功的clone,還要了解什么是"影子clone"和"深度clone"。

什么是影子clone?

下面的例子包含三個類UnCloneA,CloneB,CloneMain。CloneB類包含了一個UnCloneA的實(shí)例和一個int類型變量,并且 重載clone()方法。CloneMain類初始化UnCloneA類的一個實(shí)例b1,然后調(diào)用clone()方法生成了一個b1的拷貝b2。最后考察 一下b1和b2的輸出:

package clone;
class UnCloneA {
private int i;
public UnCloneA(int ii) { i = ii; }
public void doublevalue() { i *= 2; }
public String toString() {
return Integer.toString(i);
}
}
class CloneB implements Cloneable{
public int aInt;
public UnCloneA unCA = new UnCloneA(111);
public Object clone(){
CloneB o = null;
try{
o = (CloneB)super.clone();
}catch(CloneNotSupportedException e){ 
 

 
 

 
 

 
--------------------------------------------------------------------------------
 
4 JAVA中的指針,引用及對象的clone 

 e.printStackTrace();
}
return o;
}
}
public class CloneMain {
public static void main(String[] a){
CloneB b1 = new CloneB();
b1.aInt = 11;
System.out.println("before clone,b1.aInt = "+ b1.aInt);
System.out.println("before clone,b1.unCA = "+ b1.unCA);

CloneB b2 = (CloneB)b1.clone();
b2.aInt = 22;
b2.unCA.doublevalue();
System.out.println("=================================");
System.out.println("after clone,b1.aInt = "+ b1.aInt);
System.out.println("after clone,b1.unCA = "+ b1.unCA);
System.out.println("=================================");
System.out.println("after clone,b2.aInt = "+ b2.aInt);
System.out.println("after clone,b2.unCA = "+ b2.unCA);
}
}


/** RUN RESULT:
before clone,b1.aInt = 11
before clone,b1.unCA = 111
=================================
after clone,b1.aInt = 11
after clone,b1.unCA = 222
=================================
after clone,b2.aInt = 22
after clone,b2.unCA = 222
*/

輸出的結(jié)果說明int類型的變量aInt和UnCloneA的實(shí)例對象unCA的clone結(jié)果不一致,int類型是真正的被clone了,因?yàn)楦淖兞?b2中的aInt變量,對b1的aInt沒有產(chǎn)生影響,也就是說,b2.aInt與b1.aInt已經(jīng)占據(jù)了不同的內(nèi)存空間,b2.aInt是 b1.aInt的一個真正拷貝。相反,對b2.unCA的改變同時改變了b1.unCA,很明顯,b2.unCA和b1.unCA是僅僅指向同一個對象的 不同引用!從中可以看出,調(diào)用Object類中clone()方法產(chǎn)生的效果是:先在內(nèi)存中開辟一塊和原始對象一樣的空間,然后原樣拷貝原始對象中的內(nèi) 容。對基本數(shù)據(jù)類型,這樣的操作是沒有問題的,但對非基本類型變量,我們知道它們保存的僅僅是對象的引用,這也導(dǎo)致clone后的非基本類型變量和原始對 象中相應(yīng)的變量指向的是同一個對象。

大多時候,這種clone的結(jié)果往往不是我們所希望的結(jié)果,這種clone也被稱為"影子clone"。要想讓b2.unCA指向與b2.unCA不同的 對象,而且b2.unCA中還要包含b1.unCA中的信息作為初始信息,就要實(shí)現(xiàn)深度clone。

怎么進(jìn)行深度clone?

上面的例子改成深度clone很簡單,需要兩個改變:一是讓UnCloneA類也實(shí)現(xiàn)和CloneB類一樣的clone功能(實(shí)現(xiàn)Cloneable接 口,重載clone()方法)。二是在CloneB的clone()方法中加入一句o.unCA = (UnCloneA)unCA.clone();

程序如下:

package clone.ext;
class UnCloneA implements Cloneable{
private int i;
public UnCloneA(int ii) { i = ii; }
public void doublevalue() { i *= 2; }
public String toString() {
return Integer.toString(i);
}
public Object clone(){
UnCloneA o = null;
try{
o = (UnCloneA)super.clone();
}catch(CloneNotSupportedException e){
e.printStackTrace();
}
return o;
}
}
class CloneB implements Cloneable{
public int aInt;
public UnCloneA unCA = new UnCloneA(111);
public Object clone(){
CloneB o = null;
try{
o = (CloneB)super.clone();
}catch(CloneNotSupportedException e){
e.printStackTrace();
}
o.unCA = (UnCloneA)unCA.clone();
return o;
}
}
public class CloneMain {
public static void main(String[] a){
CloneB b1 = new CloneB();
b1.aInt = 11;
System.out.println("before clone,b1.aInt = "+ b1.aInt);
System.out.println("before clone,b1.unCA = "+ b1.unCA);

CloneB b2 = (CloneB)b1.clone();
b2.aInt = 22;
b2.unCA.doublevalue();
System.out.println("================================="); 
 

 
 

 
 

 
--------------------------------------------------------------------------------
 
5 JAVA中的指針,引用及對象的clone 

 System.out.println("after clone,b1.aInt = "+ b1.aInt);
System.out.println("after clone,b1.unCA = "+ b1.unCA);
System.out.println("=================================");
System.out.println("after clone,b2.aInt = "+ b2.aInt);
System.out.println("after clone,b2.unCA = "+ b2.unCA);
}
}

/** RUN RESULT:
before clone,b1.aInt = 11
before clone,b1.unCA = 111
=================================
after clone,b1.aInt = 11
after clone,b1.unCA = 111
=================================
after clone,b2.aInt = 22
after clone,b2.unCA = 222
*/

可以看出,現(xiàn)在b2.unCA的改變對b1.unCA沒有產(chǎn)生影響。此時b1.unCA與b2.unCA指向了兩個不同的UnCloneA實(shí)例,而且在 CloneB b2 = (CloneB)b1.clone();調(diào)用的那一刻b1和b2擁有相同的值,在這里,b1.i = b2.i = 11。

要知道不是所有的類都能實(shí)現(xiàn)深度clone的。例如,如果把上面的CloneB類中的UnCloneA類型變量改成StringBuffer類型,看一下 JDK API中關(guān)于StringBuffer的說明,StringBuffer沒有重載clone()方法,更為嚴(yán)重的是StringBuffer還是一個 final類,這也是說我們也不能用繼承的辦法間接實(shí)現(xiàn)StringBuffer的clone。如果一個類中包含有StringBuffer類型對象或和 StringBuffer相似類的對象,我們有兩種選擇:要么只能實(shí)現(xiàn)影子clone,要么就在類的clone()方法中加一句(假設(shè)是 SringBuffer對象,而且變量名仍是unCA): o.unCA = new StringBuffer(unCA.toString()); //原來的是:o.unCA = (UnCloneA)unCA.clone();

還要知道的是除了基本數(shù)據(jù)類型能自動實(shí)現(xiàn)深度clone以外,String對象是一個例外,它c(diǎn)lone后的表現(xiàn)好象也實(shí)現(xiàn)了深度clone,雖然這只是一個假象,但卻大大方便了我們的編程。

Clone中String和StringBuffer的區(qū)別

應(yīng)該說明的是,這里不是著重說明String和StringBuffer的區(qū)別,但從這個例子里也能看出String類的一些與眾不同的地方。

下面的例子中包括兩個類,CloneC類包含一個String類型變量和一個StringBuffer類型變量,并且實(shí)現(xiàn)了clone()方法。在 StrClone類中聲明了CloneC類型變量c1,然后調(diào)用c1的clone()方法生成c1的拷貝c2,在對c2中的String和 StringBuffer類型變量用相應(yīng)的方法改動之后打印結(jié)果:

package clone;
class CloneC implements Cloneable{
public String str;
public StringBuffer strBuff;
public Object clone(){
CloneC o = null;
try{
o = (CloneC)super.clone();
}catch(CloneNotSupportedException e){
e.printStackTrace();
}
return o;
}

}
public class StrClone {
public static void main(String[] a){
CloneC c1 = new CloneC();
c1.str = new String("initializeStr");
c1.strBuff = new StringBuffer("initializeStrBuff");
System.out.println("before clone,c1.str = "+ c1.str);
System.out.println("before clone,c1.strBuff = "+ c1.strBuff);

CloneC c2 = (CloneC)c1.clone();
c2.str = c2.str.substring(0,5);
c2.strBuff = c2.strBuff.append(" change strBuff clone");
System.out.println("=================================");
System.out.println("after clone,c1.str = "+ c1.str);
System.out.println("after clone,c1.strBuff = "+ c1.strBuff);
System.out.println("=================================");
System.out.println("after clone,c2.str = "+ c2.str);
System.out.println("after clone,c2.strBuff = "+ c2.strBuff);
}
}
/* RUN RESULT
before clone,c1.str = initializeStr
before clone,c1.strBuff = initializeStrBuff
=================================
after clone,c1.str = initializeStr
after clone,c1.strBuff = initializeStrBuff change strBuff clone
=================================
after clone,c2.str = initi
after clone,c2.strBuff = initializeStrBuff change strBuff clone
*
*/

打印的結(jié)果可以看出,String類型的變量好象已經(jīng)實(shí)現(xiàn)了深度clone,因?yàn)閷2.str的改動并沒有影響到c1.str!難道Java把 Sring類看成了基本數(shù)據(jù)類型?其實(shí)不然,這里有一個小小的把戲,秘密就在于c2.str = c2.str.substring(0,5)這一語句!實(shí)質(zhì)上,在clone的時候c1.str與c2.str仍然是引用,而且都指向了同一個 String對象。但在執(zhí)行c2.str = c2.str.substring(0,5)的時候,它作用相當(dāng)于生成了一個新的String類型,然后又賦回給c2.str。這是因?yàn)镾tring被 Sun公司的工程師寫成了一個不可更改的類(immutable class),在所有String類中的函數(shù)都不能更改自身的值。下面給出很簡單的一個例子:

package clone; public class StrTest { public static void main(String[] args) { String str1 = "This is a test for immutable"; String str2 = str1.substring(0,8); System.out.println("print str1 : " + str1); System.out.println("print str2 : " + str2); } } /* RUN RESULT print str1 : This is a test for immutable print str2 : This is */

例子中,雖然str1調(diào)用了substring()方法,但str1的值并沒有改變。類似的,String類中的其它方法也是如此。當(dāng)然如果我們把最上面的例子中的這兩條語句

c2.str = c2.str.substring(0,5);
c2.strBuff = c2.strBuff.append(" change strBuff clone");

改成下面這樣:

c2.str.substring(0,5);
c2.strBuff.append(" change strBuff clone");

去掉了重新賦值的過程,c2.str也就不能有變化了,我們的把戲也就露餡了。但在編程過程中只調(diào)用

c2.str.substring(0,5);

語句是沒有任何意義的。

應(yīng)該知道的是在Java中所有的基本數(shù)據(jù)類型都有一個相對應(yīng)的類,象Integer類對應(yīng)int類型,Double類對應(yīng)double類型等等,這些類也 與String類相同,都是不可以改變的類。也就是說,這些的類中的所有方法都是不能改變其自身的值的。這也讓我們在編clone類的時候有了一個更多的 選擇。同時我們也可以把自己的類編成不可更改的類
 

posted on 2011-02-14 20:57 luis 閱讀(549) 評論(0)  編輯 收藏 引用

只有注冊用戶登錄后才能發(fā)表評論。
網(wǎng)站導(dǎo)航: 博客園   IT新聞   BlogJava   博問   Chat2DB   管理


<2009年6月>
31123456
78910111213
14151617181920
21222324252627
2829301234
567891011

常用鏈接

留言簿(3)

隨筆分類

隨筆檔案

文章分類

文章檔案

友情鏈接

搜索

  •  

最新評論

閱讀排行榜

評論排行榜

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            欧美二区在线观看| 欧美在线网址| 欧美视频精品在线观看| 欧美成人午夜剧场免费观看| 久久视频在线视频| 欧美丰满高潮xxxx喷水动漫| 欧美日韩的一区二区| 国产精品成人在线观看| 国产欧美一级| 亚洲激情小视频| 亚洲桃花岛网站| 欧美在线高清| 亚洲国产99精品国自产| 99国产欧美久久久精品| 香蕉成人久久| 每日更新成人在线视频| 国产精品www.| 亚洲黄色免费网站| 欧美亚洲日本网站| 欧美激情一区二区三区在线| 在线综合欧美| 久热这里只精品99re8久| 欧美日韩黄视频| 狠狠色综合色区| 亚洲视频在线观看免费| 久久综合狠狠综合久久综合88 | 久久夜色精品国产欧美乱极品 | 伊甸园精品99久久久久久| 亚洲裸体俱乐部裸体舞表演av| 亚洲欧美日韩一区二区三区在线| 麻豆成人小视频| 亚洲欧美日韩国产另类专区| 欧美高清在线一区| 亚洲国产精品久久91精品| 久久精品成人| 亚洲一区黄色| 欧美日韩视频在线一区二区| 亚洲国产一区在线| 久久久久久久久久码影片| aa亚洲婷婷| 欧美激情中文不卡| 亚洲国产精品久久久久秋霞影院 | 久久国产精品久久久| 亚洲靠逼com| 欧美韩日视频| 亚洲二区三区四区| 久久精品最新地址| 亚洲专区一二三| 欧美色视频日本高清在线观看| 1204国产成人精品视频| 久久精品主播| 亚洲国产mv| 亚洲人成网站在线观看播放| 欧美一区二区三区在线观看| 亚洲九九九在线观看| 欧美成人免费在线视频| 1000部精品久久久久久久久| 另类春色校园亚洲| 久久香蕉国产线看观看网| 在线电影一区| 你懂的视频一区二区| 久久精品国产精品亚洲| 狠狠入ady亚洲精品| 麻豆国产va免费精品高清在线| 欧美一级免费视频| 国产一区二区精品久久91| 欧美在线亚洲一区| 欧美在线你懂的| 亚洲第一成人在线| 欧美二区视频| 欧美激情国产日韩精品一区18| 亚洲精品日韩在线| 亚洲精品永久免费| 国产精品jizz在线观看美国| 午夜久久资源| 欧美一区二区精品久久911| 国产一区二区三区黄| 噜噜噜久久亚洲精品国产品小说| 久久偷窥视频| 国产精品99久久久久久白浆小说| 亚洲午夜一级| 伊人久久婷婷| 亚洲另类春色国产| 国产精品日本精品| 久久一区二区三区国产精品| 美女诱惑一区| 亚洲男人第一网站| 久久成人综合视频| 99精品国产高清一区二区 | 日韩视频免费在线观看| 国产精品日日做人人爱| 男男成人高潮片免费网站| 欧美国产日本| 欧美亚洲免费高清在线观看| 噜噜噜久久亚洲精品国产品小说| 日韩视频第一页| 午夜精品久久久久久久男人的天堂| 精品成人免费| 在线一区视频| 最新中文字幕亚洲| 性久久久久久| 一区二区三区欧美激情| 久久福利资源站| 亚洲图片欧美午夜| 老色鬼精品视频在线观看播放| 亚洲网友自拍| 久久综合给合久久狠狠狠97色69| 亚洲天堂第二页| 嫩模写真一区二区三区三州| 欧美在线一二三| 欧美偷拍一区二区| 亚洲国产天堂网精品网站| 国产亚洲综合性久久久影院| 亚洲日韩欧美视频一区| 久久亚洲高清| 国产精品久久久久aaaa| 亚洲国产福利在线| …久久精品99久久香蕉国产| 亚洲欧美在线另类| 亚洲天堂久久| 欧美日韩视频在线第一区| 亚洲第一网站免费视频| 激情综合亚洲| 欧美伊人久久| 久久精品日产第一区二区| 欧美午夜免费影院| 亚洲毛片网站| 一本大道久久精品懂色aⅴ| 久久蜜桃精品| 久久综合图片| 一色屋精品视频在线看| 久久久久久久久久久久久久一区 | 亚洲人成在线观看| 亚洲国产另类久久精品| 久久全国免费视频| 免费亚洲电影在线| 亚洲激情网址| 欧美激情第五页| 亚洲国产精品久久久久婷婷老年| 亚洲电影第1页| 久久综合影视| 亚洲第一网站| 亚洲视频综合| 国产精品久久久久久五月尺| 亚洲视频高清| 久久国产成人| 亚洲电影免费观看高清| 欧美风情在线观看| 一区二区免费在线视频| 亚洲欧美国产另类| 国产欧美日韩亚洲一区二区三区| 午夜在线电影亚洲一区| 久久亚洲私人国产精品va媚药| 一区二区自拍| 欧美激情视频免费观看| 99在线|亚洲一区二区| 香蕉精品999视频一区二区| 国产亚洲综合在线| 蜜臀av一级做a爰片久久| 亚洲区国产区| 久久成人在线| 亚洲精品一二三区| 国产精品欧美久久| 久久久久成人精品| 日韩亚洲精品视频| 亚欧美中日韩视频| 亚洲国产精品国自产拍av秋霞| 欧美日韩国产美女| 亚洲欧美影音先锋| 欧美成人一区二区三区在线观看| 日韩一级不卡| 国内精品国产成人| 欧美日韩一区二区三区四区在线观看 | 欧美黄色小视频| 亚洲免费一区二区| 欧美激情按摩在线| 欧美一区免费视频| 亚洲久久一区二区| 亚洲精品视频一区| 国产亚洲精品久久久久婷婷瑜伽| 久久久久久亚洲综合影院红桃| 99视频有精品| 欧美激情综合色| 欧美一区1区三区3区公司| 91久久久久久久久| 国语自产精品视频在线看8查询8| 欧美精品xxxxbbbb| 久久久另类综合| 欧美一区二区免费视频| 一区二区三区精品视频在线观看| 麻豆国产精品777777在线| 性色av一区二区三区| 99国产精品国产精品久久| 国产亚洲精品久久久久婷婷瑜伽| 欧美日韩中文字幕精品| 欧美激情a∨在线视频播放| 久久久在线视频| 欧美资源在线| 欧美一级大片在线观看| 午夜国产精品视频免费体验区|