国产成人精品18p,天天干成人网,无码专区狠狠躁天天躁,美女脱精光隐私扒开免费观看

Java中怎么創(chuàng )建和銷(xiāo)毀對象

發(fā)布時(shí)間:2021-07-04 20:13 來(lái)源:億速云 閱讀:0 作者:Leah 欄目: 開(kāi)發(fā)技術(shù)

這篇文章將為大家詳細講解有關(guān)Java中怎么創(chuàng )建和銷(xiāo)毀對象,文章內容質(zhì)量較高,因此小編分享給大家做個(gè)參考,希望大家閱讀完這篇文章后對相關(guān)知識有一定的了解。

一、考慮用靜態(tài)工廠(chǎng)方法代替構造器:

構造器是創(chuàng )建一個(gè)對象實(shí)例最基本也最通用的方法,大部分開(kāi)發(fā)者在使用某個(gè)class的時(shí)候,首先需要考慮的就是如何構造和初始化一個(gè)對象示例,而構造的方式首先考慮到的就是通過(guò)構造函數來(lái)完成,因此在看javadoc中的文檔時(shí)首先關(guān)注的函數也是構造器。然而在有些時(shí)候構造器并非我們***的選擇,通過(guò)反射也是可以輕松達到的。我們這里主要提到的方式是通過(guò)靜態(tài)類(lèi)工廠(chǎng)的方式來(lái)創(chuàng )建class的實(shí)例,如:

public static Boolean valueOf(boolean b) {           return b ? Boolean.TRUE : Boolean.FALSE;       }

靜態(tài)工廠(chǎng)方法和構造器不同有以下主要優(yōu)勢:

1. 有意義的名稱(chēng)。

在框架設計中,針對某些工具類(lèi)通常會(huì )考慮dummy對象或者空對象以辨別該對象是否已經(jīng)被初始化,如我曾在我的C++基礎庫中實(shí)現了String類(lèi)型,見(jiàn)如下代碼:

void showExample() {           String strEmpty = String::empty();           String strEmpty2 = "";           String strData = String::prellocate(1024);           if (strEmpty.isEmpty()) {               //TODO: do something           }       }       static String String::emptyString;       String& String::empty() {           return emptyString;       }               bool String::isEmpty() {           if (this->_internal == &emptyString->_internal)               return true;           //TODO: do other justice to verify whether it is empty.       }

在上面的代碼中,提供了兩個(gè)靜態(tài)工廠(chǎng)方法empty和preallocate用于分別創(chuàng )建一個(gè)空對象和一個(gè)帶有指定分配空間的String對象。從使用方式來(lái)看,這些靜態(tài)方法確實(shí)提供了有意義的名稱(chēng),使用者很容易就可以判斷出它們的作用和應用場(chǎng)景,而不必在一組重載的構造器中去搜尋每一個(gè)構造函數及其參數列表,以找出適合當前場(chǎng)景的構造函數。從效率方面來(lái)講,由于提供了***的靜態(tài)空對象,當判讀對象實(shí)例是否為空時(shí)(isEmpty),直接使用預制靜態(tài)空對象(emptyString)的地址與當前對象進(jìn)行比較,如果是同一地址,即可確認當前實(shí)例為空對象了。對于preallocate函數,顧名思義,該函數預分配了指定大小的內存空間,后面在使用該String實(shí)例時(shí),不必擔心賦值或追加的字符過(guò)多而導致頻繁的realloc等操作。

2. 不必在每次調用它們的時(shí)候創(chuàng )建一個(gè)新的對象。

還是基于上面的代碼實(shí)例,由于所有的空對象都共享同一個(gè)靜態(tài)空對象,這樣也節省了更多的內存開(kāi)銷(xiāo),如果是strEmpty2方式構造出的空對象,在執行比較等操作時(shí)會(huì )帶來(lái)更多的效率開(kāi)銷(xiāo)。事實(shí)上,Java在String對象的實(shí)現中,使用了常量資源池也是基于了同樣的優(yōu)化策略。該優(yōu)勢同樣適用于單實(shí)例模式。

3. 可以返回原返回類(lèi)型的任何子類(lèi)型。

在Java Collections Framework的集合接口中,提供了大量的靜態(tài)方法返回集合接口類(lèi)型的實(shí)現類(lèi)型,如Collections.subList()、Collections.unmodifiableList()等。返回的接口是明確的,然而針對具體的實(shí)現類(lèi),函數的使用者并不也無(wú)需知曉。這樣不僅極大的減少了導出類(lèi)的數量,而且在今后如果發(fā)現某個(gè)子類(lèi)的實(shí)現效率較低或者發(fā)現更好的數據結構和算法來(lái)替換當前實(shí)現子類(lèi)時(shí),對于集合接口的使用者來(lái)說(shuō),不會(huì )帶來(lái)任何的影響。本書(shū)在例子中提到EnumSet是通過(guò)靜態(tài)工廠(chǎng)方法返回對象實(shí)例的,沒(méi)有提供任何構造函數,其內部在返回實(shí)現類(lèi)時(shí)做了一個(gè)優(yōu)化,即如果枚舉的數量小于64,該工廠(chǎng)方法將返回一個(gè)經(jīng)過(guò)特殊優(yōu)化的實(shí)現類(lèi)實(shí)(RegularEnumSet),其內部使用long(64bits在Java中) 中的不同位來(lái)表示不同的枚舉值。如果枚舉的數量大于64,將使用long的數組作為底層支撐。然而這些內部實(shí)現類(lèi)的優(yōu)化對于使用者來(lái)說(shuō)是透明的。

4. 在創(chuàng )建參數化類(lèi)型實(shí)例的時(shí)候,它們使代碼變得更加簡(jiǎn)潔。

Map<String,String> m = new HashMap<String,String>();

由于Java在構造函數的調用中無(wú)法進(jìn)行類(lèi)型的推演,因此也就無(wú)法通過(guò)構造器的參數類(lèi)型來(lái)實(shí)例化指定類(lèi)型參數的實(shí)例化對象。然而通過(guò)靜態(tài)工廠(chǎng)方法則可以利用參數類(lèi)型推演的優(yōu)勢,避免了類(lèi)型參數在一次聲明中被多次重寫(xiě)所帶來(lái)的煩憂(yōu),見(jiàn)如下代碼:

public static <K,V> HashMap<K,V> newInstance() {            return new HashMap<K,V>();        }        Map<String,String> m = MyHashMap.newInstance();

二、遇到多個(gè)構造參數時(shí)要考慮用構建器(Builder模式):

如果一個(gè)class在構造初始化的時(shí)候存在非常多的參數,將會(huì )導致構造函數或者靜態(tài)工廠(chǎng)函數帶有大量的、類(lèi)型相同的函數參數,特別是當一部分參數只是可選參數的時(shí)候,class的使用者不得不為這些可選參數也傳入缺省值,有的時(shí)候會(huì )發(fā)現使用者傳入的缺省值可能是有意義的,而并非class內部實(shí)現所認可的缺省值,比如某個(gè)整型可選參數,通常使用者會(huì )傳入0,然后class內部的實(shí)現恰恰認為0是一種重要的狀態(tài),而該狀態(tài)并不是該調用者關(guān)心的,但是該狀態(tài)卻間接導致其他狀態(tài)的改變,因而帶來(lái)了一些潛在的狀態(tài)不一致問(wèn)題。與此同時(shí),過(guò)多的函數參數也給使用者的學(xué)習和使用帶來(lái)很多不必要的麻煩,我相信任何使用者都希望看到class的接口是簡(jiǎn)單易用、函數功能清晰可見(jiàn)的。在Effective C++中針對接口的設計有這樣的一句話(huà):"接口要完滿(mǎn)而最小化"。針對該類(lèi)問(wèn)題通常會(huì )考慮的方法是將所有的參數歸結到一個(gè)JavaBean對象中,實(shí)例化這個(gè)Bean對象,然后再將實(shí)例化的結果傳給這個(gè)class的構造函數,這種方法仍然沒(méi)有避免缺省值的問(wèn)題。該條目推薦了Builder模式來(lái)創(chuàng )建這個(gè)帶有很多可選參數的實(shí)例對象。

class NutritionFacts {           private final int servingSize;           private final int servings;           private final int calories;           private final int fat;           private final int sodium;           private final int carbohydrate;           public static class Builder {               //對象的必選參數               private final int servingSize;               private final int servings;               //對象的可選參數的缺省值初始化               private int calories = 0;               private int fat = 0;               private int carbohydrate = 0;               private int sodium = 0;               //只用少數的必選參數作為構造器的函數參數               public Builder(int servingSize,int servings) {                   this.servingSize = servingSize;                   this.servings = servings;               }               public Builder calories(int val) {                   calories = val;                   return this;               }               public Builder fat(int val) {                   fat = val;                   return this;               }               public Builder carbohydrate(int val) {                   carbohydrate = val;                   return this;               }               public Builder sodium(int val) {                   sodium = val;                   return this;               }               public NutritionFacts build() {                   return new NutritionFacts(this);               }           }           private NutritionFacts(Builder builder) {               servingSize = builder.servingSize;               servings = builder.servings;               calories = builder.calories;               fat = builder.fat;               sodium = builder.sodium;               carbohydrate = builder.carbohydrate;           }       }       //使用方式       public static void main(String[] args) {           NutritionFacts cocaCola = new NutritionFacts.Builder(240, 8).calories(100)               .sodium(35).carbohydrate(27).build();           System.out.println(cocaCola);       }

對于Builder方式,可選參數的缺省值問(wèn)題也將不再困擾著(zhù)所有的使用者。這種方式還帶來(lái)了一個(gè)間接的好處是,不可變對象的初始化以及參數合法性的驗證等工作在構造函數中原子性的完成了。

三、用私有構造器或者枚舉類(lèi)型強化Singleton屬性:

對于單實(shí)例模式,相信很多開(kāi)發(fā)者并不陌生,然而如何更好更安全的創(chuàng )建單實(shí)例對象還是需要一些推敲和斟酌的,在Java中主要的創(chuàng )建方式有以下三種,我們分別作出解釋和適當的比較。

1. 將構造函數私有化,直接通過(guò)靜態(tài)公有的final域字段獲取單實(shí)例對象:

public class Elvis {           public static final Elvis INSTANCE = new Elvis();           private Elivs() { ... }           public void leaveTheBuilding() { ... }       }

這樣的方式主要優(yōu)勢在于簡(jiǎn)潔高效,使用者很快就能判定當前類(lèi)為單實(shí)例類(lèi),在調用時(shí)直接操作Elivs.INSTANCE即可,由于沒(méi)有函數的調用,因此效率也非常高效。然而事物是具有一定的雙面性的,這種設計方式在一個(gè)方向上走的過(guò)于極端了,因此他的缺點(diǎn)也會(huì )是非常明顯的。如果今后Elvis的使用代碼被遷移到多線(xiàn)程的應用環(huán)境下了,系統希望能夠做到每個(gè)線(xiàn)程使用同一個(gè)Elvis實(shí)例,不同線(xiàn)程之間則使用不同的對象實(shí)例。那么這種創(chuàng )建方式將無(wú)法實(shí)現該需求,因此需要修改接口以及接口的調用者代碼,這樣就帶來(lái)了更高的修改成本。

2. 通過(guò)公有域成員的方式返回單實(shí)例對象:

public class Elvis {           public static final Elvis INSTANCE = new Elvis();           private Elivs() { ... }           public static Elvis getInstance() { return INSTANCE; }           public void leaveTheBuilding() { ... }       }

這種方法很好的彌補了***種方式的缺陷,如果今后需要適應多線(xiàn)程環(huán)境的對象創(chuàng )建邏輯,僅需要修改Elvis的getInstance()方法內部即可,對用調用者而言則是不變的,這樣便極大的縮小了影響的范圍。至于效率問(wèn)題,現今的JVM針對該種函數都做了很好的內聯(lián)優(yōu)化,因此不會(huì )產(chǎn)生因函數頻繁調用而帶來(lái)的開(kāi)銷(xiāo)。

3. 使用枚舉的方式(Java SE5):

public enum Elvis {          INSTANCE;          public void leaveTheBuilding() { ... }      }

就目前而言,這種方法在功能上和公有域方式相近,但是他更加簡(jiǎn)潔更加清晰,擴展性更強也更加安全。

我在設計自己的表達式解析器時(shí),曾將所有的操作符設計為enum中不同的枚舉元素,同時(shí)提供了帶有參數的構造函數,傳入他們的優(yōu)先級、操作符名稱(chēng)等信息。

四、通過(guò)私有構造器強化不可實(shí)例化的能力:

對于有些工具類(lèi)如java.lang.Math、java.util.Arrays等,其中只是包含了靜態(tài)方法和靜態(tài)域字段,因此對這樣的class實(shí)例化就顯得沒(méi)有任何意義了。然而在實(shí)際的使用中,如果不加任何特殊的處理,這樣的classes是可以像其他classes一樣被實(shí)例化的。這里介紹了一種方式,既將缺省構造函數設置為private,這樣類(lèi)的外部將無(wú)法實(shí)例化該類(lèi),與此同時(shí),在這個(gè)私有的構造函數的實(shí)現中直接拋出異常,從而也避免了類(lèi)的內部方法調用該構造函數。

public class UtilityClass {           //Suppress default constructor for noninstantiability.           private UtilityClass() {               throw new AssertionError();           }       }

這樣定義之后,該類(lèi)將不會(huì )再被外部實(shí)例化了,否則會(huì )產(chǎn)生編譯錯誤。然而這樣的定義帶來(lái)的最直接的負面影響是該類(lèi)將不能再被子類(lèi)化。

五、避免創(chuàng )建不必要的對象:

試比較以下兩行代碼在被多次反復執行時(shí)的效率差異:由于String被實(shí)現為不可變對象,JVM底層將其實(shí)現為常量池,既所有值等于"stringette" 的String對象實(shí)例共享同一對象地址,而且還可以保證,對于所有在同一JVM中運行的代碼,只要他們包含相同的字符串字面常量,該對象就會(huì )被重用。

我們繼續比較下面的例子,并測試他們在運行時(shí)的效率差異:

Boolean b = Boolean.valueOf("true");  Boolean b = new Boolean("true");

前者通過(guò)靜態(tài)工廠(chǎng)方法保證了每次返回的對象,如果他們都是true或false,那么他們將返回相同的對象。換句話(huà)說(shuō),valueOf將只會(huì )返回Boolean.TRUE或Boolean.FALSE兩個(gè)靜態(tài)域字段之一。而后面的Boolean構造方式,每次都會(huì )構造出一個(gè)新的Boolean實(shí)例對象。這樣在多次調用后,***種靜態(tài)工廠(chǎng)方法將會(huì )避免大量不必要的Boolean對象被創(chuàng )建,從而提高了程序的運行效率,也降低了垃圾回收的負擔。

繼續比較下面的代碼:

public class Person {           private final Date birthDate;           //判斷該嬰兒是否是在生育高峰期出生的。           public boolean isBabyBoomer {               Calender c = Calendar.getInstance(TimeZone.getTimeZone("GMT"));               c.set(1946,Calendar.JANUARY,1,0,0,0);               Date dstart = c.getTime();               c.set(1965,Calendar.JANUARY,1,0,0,0);               Date dend = c.getTime();               return birthDate.compareTo(dstart) >= 0 && birthDate.compareTo(dend) < 0;           }       }              public class Person {           private static final Date BOOM_START;           private static final Date BOOM_END;                      static {               Calender c = Calendar.getInstance(TimeZone.getTimeZone("GMT"));               c.set(1946,Calendar.JANUARY,1,0,0,0);               BOOM_START = c.getTime();               c.set(1965,Calendar.JANUARY,1,0,0,0);               BOOM_END = c.getTime();           }           public boolean isBabyBoomer() {               return birthDate.compareTo(BOOM_START) >= 0 && birthDate.compareTo(BOOM_END) < 0;           }       }

改進(jìn)后的Person類(lèi)只是在初始化的時(shí)候創(chuàng )建Calender、TimeZone和Date實(shí)例一次,而不是在每次調用isBabyBoomer方法時(shí)都創(chuàng )建一次他們。如果該方法會(huì )被頻繁調用,效率的提升將會(huì )極為顯著(zhù)。

集合框架中的Map接口提供keySet方法,該方法每次都將返回底層原始Map對象鍵數據的視圖,而并不會(huì )為該操作創(chuàng )建一個(gè)Set對象并填充底層Map所有鍵的對象拷貝。因此當多次調用該方法并返回不同的Set對象實(shí)例時(shí),事實(shí)上他們底層指向的將是同一段數據的引用。

在該條目中還提到了自動(dòng)裝箱行為給程序運行帶來(lái)的性能沖擊,如果可以通過(guò)原始類(lèi)型完成的操作應該盡量避免使用裝箱類(lèi)型以及他們之間的交互使用。見(jiàn)下例:

public static void main(String[] args) {           Long sum = 0L;           for (long i = 0; i < Integer.MAX_VALUE; ++i) {               sum += i;           }           System.out.println(sum);       }

本例中由于錯把long sum定義成Long sum,其效率降低了近10倍,這其中的主要原因便是該錯誤導致了2的31次方個(gè)臨時(shí)Long對象被創(chuàng )建了。

六、消除過(guò)期的對象引用:

盡管Java不像C/C++那樣需要手工管理內存資源,而是通過(guò)更為方便、更為智能的垃圾回收機制來(lái)幫助開(kāi)發(fā)者清理過(guò)期的資源。即便如此,內存泄露問(wèn)題仍然會(huì )發(fā)生在你的程序中,只是和C/C++相比,Java中內存泄露更加隱匿,更加難以發(fā)現,見(jiàn)如下代碼:

public class Stack {           private Object[] elements;           private int size = 0;           private static final int DEFAULT_INITIAL_CAPACITY = 16;           public Stack() {               elements = new Object[DEFAULT_INITIAL_CAPACITY];           }           public void push(Object e) {               ensureCapacity();               elements[size++] = e;           }           public Object pop() {               if (size == 0)                    throw new EmptyStackException();               return elements[--size];           }           private void ensureCapacity() {               if (elements.length == size)                   elements = Arrays.copys(elements,2*size+1);           }       }

以上示例代碼,在正常的使用中不會(huì )產(chǎn)生任何邏輯問(wèn)題,然而隨著(zhù)程序運行時(shí)間不斷加長(cháng),內存泄露造成的副作用將會(huì )慢慢的顯現出來(lái),如磁盤(pán)頁(yè)交換、OutOfMemoryError等。那么內存泄露隱藏在程序中的什么地方呢?當我們調用pop方法是,該方法將返回當前棧頂的elements,同時(shí)將該棧的活動(dòng)區間(size)減一,然而此時(shí)被彈出的Object仍然保持至少兩處引用,一個(gè)是返回的對象,另一個(gè)則是該返回對象在elements數組中原有棧頂位置的引用。這樣即便外部對象在使用之后不再引用該Object,那么它仍然不會(huì )被垃圾收集器釋放,久而久之導致了更多類(lèi)似對象的內存泄露。修改方式如下:

public Object pop() {           if (size == 0)                throw new EmptyStackException();           Object result = elements[--size];           elements[size] = null; //手工將數組中的該對象置空           return result;       }

由于現有的Java垃圾收集器已經(jīng)足夠只能和強大,因此沒(méi)有必要對所有不在需要的對象執行obj = null的顯示置空操作,這樣反而會(huì )給程序代碼的閱讀帶來(lái)不必要的麻煩,該條目只是推薦在以下3中情形下需要考慮資源手工處理問(wèn)題:

1) 類(lèi)是自己管理內存,如例子中的Stack類(lèi)。

2) 使用對象緩存機制時(shí),需要考慮被從緩存中換出的對象,或是長(cháng)期不會(huì )被訪(fǎng)問(wèn)到的對象。

3) 事件監聽(tīng)器和相關(guān)回調。用戶(hù)經(jīng)常會(huì )在需要時(shí)顯示的注冊,然而卻經(jīng)常會(huì )忘記在不用的時(shí)候注銷(xiāo)這些回調接口實(shí)現類(lèi)。

七、避免使用終結方法:

任何事情都存在其一定的雙面性或者多面性,對于C++的開(kāi)發(fā)者,內存資源是需要手工分配和釋放的,而對于Java和C#這種資源托管的開(kāi)發(fā)語(yǔ)言,更多的工作可以交給虛擬機的垃圾回收器來(lái)完成,由此C++程序得到了運行效率,卻失去了安全。在Java的實(shí)際開(kāi)發(fā)中,并非所有的資源都是可以被垃圾回收器自動(dòng)釋放的,如FileInputStream、Graphic2D等class中使用的底層操作系統資源句柄,并不會(huì )隨著(zhù)對象實(shí)例被GC回收而被釋放,然而這些資源對于整個(gè)操作系統而言,都是非常重要的稀缺資源,更多的資源句柄泄露將會(huì )導致整個(gè)操作系統及其運行的各種服務(wù)程序的運行效率直線(xiàn)下降。那么如何保證系統資源不會(huì )被泄露了?在C++中,由于其資源完全交由開(kāi)發(fā)者自行管理,因此在決定資源何時(shí)釋放的問(wèn)題上有著(zhù)很優(yōu)雅的支持,C++中的析構函數可以說(shuō)是完成這一工作的天然候選者。任何在棧上聲明的C++對象,當棧退出或者當前對象離開(kāi)其作用域時(shí),該對象實(shí)例的析構函數都會(huì )被自動(dòng)調用,因此當函數中有任何異常(Exception)發(fā)生時(shí),在棧被銷(xiāo)毀之前,所有棧對象的析構函數均會(huì )被自動(dòng)調用。然而對于Java的開(kāi)發(fā)者而言,從語(yǔ)言自身視角來(lái)看,Java本身并未提供析構函數這樣的機制,當然這也是和其資源被JVM托管有一定關(guān)系的。

在Java中完成這樣的工作主要是依靠try-finally機制來(lái)協(xié)助完成的。然而Java中還提供了另外一種被稱(chēng)為finalizer的機制,使用者僅僅需要重載Object對象提供的finalize方法,這樣當JVM的在進(jìn)行垃圾回收時(shí),就可以自動(dòng)調用該方法。但是由于對象何時(shí)被垃圾收集的不確定性,以及finalizer給GC帶來(lái)的性能上的影響,因此并不推薦使用者依靠該方法來(lái)達到關(guān)鍵資源釋放的目的。比如,有數千個(gè)圖形句柄都在等待被終結和回收,可惜的是執行終結方法的線(xiàn)程優(yōu)先級要低于普通的工作者線(xiàn)程,這樣就會(huì )有大量的圖形句柄資源停留在finalizer的隊列中而不能被及時(shí)的釋放,最終導致了系統運行效率的下降,甚至還會(huì )引發(fā)JVM報出OutOfMemoryError的錯誤。

Java的語(yǔ)言規范中并沒(méi)有保證該方法會(huì )被及時(shí)的執行,甚至都沒(méi)有保證一定會(huì )被執行。即便開(kāi)發(fā)者在code中手工調用了System.gc和System.runFinalization這兩個(gè)方法,這僅僅是提高了finalizer被執行的幾率而已。還有一點(diǎn)需要注意的是,被重載的finalize()方法中如果拋出異常,其棧幀軌跡是不會(huì )被打印出來(lái)的。在Java中被推薦的資源釋放方法為,提供顯式的具有良好命名的接口方法,如FileInputStream.close()和Graphic2D.dispose()等。然后使用者在finally區塊中調用該方法,見(jiàn)如下代碼:

public void test() {           FileInputStream fin = null;           try {               fin = new FileInputStream(filename);               //do something.           } finally {               fin.close();           }       }

那么在實(shí)際的開(kāi)發(fā)中,利用finalizer又能給我們帶來(lái)什么樣的幫助呢?見(jiàn)下例:

public class FinalizeTest {           //@Override           protected void finalize() throws Throwable {               try {                   //在調試過(guò)程中通過(guò)該方法,打印對象在被收集前的各種狀態(tài),   //如判斷是否仍有資源未被釋放,或者是否有狀態(tài)不一致的現象存在。   //推薦將該finalize方法設計成僅在debug狀態(tài)下可用,而在release   //下該方法并不存在,以避免其對運行時(shí)效率的影響。                   System.out.println("The current status: " + _myStatus);               } finally {                   //在finally中對超類(lèi)finalize方法的調用是必須的,這樣可以保證整個(gè)class繼承   //體系中的finalize鏈都被執行。                   super.finalize();                }           }       }

免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng )、來(lái)自互聯(lián)網(wǎng)轉載和分享為主,文章觀(guān)點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權請聯(lián)系QQ:712375056 進(jìn)行舉報,并提供相關(guān)證據,一經(jīng)查實(shí),將立刻刪除涉嫌侵權內容。

亚洲永久网址在线观看| 爆乳2把你榨干哦OVA在线观看| 久久婷婷色综合一区二区| 三上悠亚公侵犯344在线观看| 久久综合精品国产二区无码 | 国产超碰人人做人人爱|