日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

java的map 使用string数组多了双引号_奥奥奥利给!!!再也不怕面试官问我String源码了!来吧...

發(fā)布時間:2025/3/11 编程问答 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java的map 使用string数组多了双引号_奥奥奥利给!!!再也不怕面试官问我String源码了!来吧... 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

簡述

字符串廣泛應用 在 Java 編程中,在 Java 中字符串屬于對象,Java 提供了String 類來創(chuàng)建和操作字符串。字符串緩沖區(qū)支持可變字符串。因為String對象是不可變的,因此可以共享它們。

String類代表字符串,Java程序中的所有字符串字面值如"abc"都是這個類的實例對象。String 類是不可改變的,所以你一旦創(chuàng)建了 String 對象,那它的值就無法改變了。如果需要對字符串做很多修改,那么應該選擇使用StringBuilder或者StringBuffer。

最簡單的創(chuàng)建字符串的方式:String qc = "qiu chan"編譯器會使用該值創(chuàng)建一個 對象。我們也可以使用關鍵字New創(chuàng)建String對象。

String類型的常量池比較特殊。它的主要使用方法有兩種:

直接使用雙引號聲明出來的String對象會直接存儲在常量池中。

如果不是用雙引號聲明的String對象,可以使用String提供的intern方法。intern 方法會從字符串常量池中查詢當前字符串是否存在,若不存在就會將當前字符串放入常量池中。

繼承/實現(xiàn)關系

public final class String implements java.io.Serializable, Comparable, CharSequence { // 省略}

String是final修飾的不能夠被繼承和修改。

源碼

String的底層使用的是char數(shù)組用于存儲。

private final char value[];

緩存字符串的哈希碼默認值為0

private int hash;

無參數(shù)構造函數(shù)

public String() { this.value = "".value;}

解析:初始化一個新創(chuàng)建的String對象,使其代表一個空字符序列。 注意,由于String是不可變的,所以不需要使用這個構造函數(shù)。

參數(shù)為字符串的構造函數(shù)

public String(String original) { this.value = original.value; this.hash = original.hash;}

解析:初始化一個新創(chuàng)建的String對象,使其代表與參數(shù)相同的字符序列。換句話說,新創(chuàng)建的字符串是參數(shù)字符串的副本。除非需要參數(shù)字符串的顯式拷貝,否則不需要使用這個構造函數(shù),因為String是不可變的。

參數(shù)為char數(shù)組的構造函數(shù)

public String(char value[]) { this.value = Arrays.copyOf(value, value.length);}

解析:分配一個新的String,使其代表當前字符數(shù)組參數(shù)中包含的字符序列。使用Arrays.copyOf方法進行字符數(shù)組的內容被復制。字符數(shù)組的后續(xù)修改不會影響新創(chuàng)建的字符串。

參數(shù)為char數(shù)組并且?guī)в衅屏康臉嬙旆椒?/h3>// value[]:作為字符源的數(shù)組,offset:偏移量、下標從0開始并且包括offset,count:從數(shù)組中取到的元素的個數(shù)。public String(char value[], int offset, int count) { // 如果偏移量小于0拋出IndexOutOfBoundsException異常 if (offset < 0) { throw new StringIndexOutOfBoundsException(offset); } // 判斷要取的元素的個數(shù)是否小于等于0 if (count <= 0) { // 要取的元素的個數(shù)小于0,拋出IndexOutOfBoundsException異常 if (count < 0) { throw new StringIndexOutOfBoundsException(count); } // 在要取的元素的個數(shù)等于0的情況下,判斷偏移量是否小于等于數(shù)組的長度 if (offset <= value.length) { // 偏移量小于等于數(shù)組的長度,返回一個空字符串數(shù)組的形式 this.value = "".value; return; } } // 如果偏移量的值大于數(shù)組的長度減去取元素的個數(shù)拋出IndexOutOfBoundsException異常 if (offset > value.length - count) { throw new StringIndexOutOfBoundsException(offset + count); } // 復制元素 this.value = Arrays.copyOfRange(value, offset, offset+count);}

解析:分配一個新的Sting,來源于給定的char數(shù)組中的字符。offset參數(shù)是子數(shù)組中第一個字符的索引,count參數(shù)指定子數(shù)組的長度。子數(shù)組被被復制以后,對字符數(shù)組的修改不會影響新創(chuàng)建的字符串。

參數(shù)為StringBuffer的構造方法

public String(StringBuffer buffer) { // 這里對StringBuffer進行了加鎖,然后再進行拷貝操作。這里對其進行加鎖正是為了保證在多線程環(huán)境下只能有一個線程去操作StringBuffer對象。 synchronized(buffer) { this.value = Arrays.copyOf(buffer.getValue(), buffer.length()); }}

解析:分配一個新的字符串,該字符串包含當前字符串緩沖區(qū)參數(shù)中包含的字符序列。Arrays.copyOf方法進行字符串緩沖區(qū)中內容的復制。這里對StringBuffer進行了加鎖,然后再進行拷貝操作。這里對其進行加鎖正是為了保證在多線程環(huán)境下只能有一個線程去操作StringBuffer對象。

參數(shù)為StringBuilder的構造方法

public String(StringBuilder builder) { this.value = Arrays.copyOf(builder.getValue(), builder.length());}

解析:參數(shù)是StringBuilder,這個是線程不安全的,但是性能相對于StringBuffer有很大的提升,源碼的注釋中說通過toString方法從字符串構建器中獲取字符串可能會運行得更快,通常是首選。

length方法

public int length() { // 查看源碼發(fā)現(xiàn),這個value是一個char數(shù)組,本質獲取的是字符串對應的char數(shù)組的長度。 return value.length; }

解析:返回此字符串的長度。查看源碼發(fā)現(xiàn),這個value是一個char數(shù)組,本質獲取的是字符串對應的char數(shù)組的長度。

isEmpty方法

public boolean isEmpty() { // 底層的char數(shù)組的長度是否為0進行判斷 return value.length == 0;}//舉例@Testpublic void test_string_isEmpty(){ System.out.println(" ".isEmpty());// true System.out.println("".isEmpty());// false}

解析:判斷給定的字符串是否為空,底層實現(xiàn)是根據(jù)char數(shù)組的長度是否為0進行判斷。

charAt方法

public char charAt(int index) { // 給定的索引小于0或者給定的索引大于這個字符串對應的char數(shù)組的長度拋出角標越界異常 if ((index < 0) || (index >= value.length)) { throw new StringIndexOutOfBoundsException(index); } // 獲取當前的指定位置的char字符 return value[index];}

解析:根據(jù)給定的索引獲取當前的指定位置的char字符。如果給定的索引否小于0,或者給定的索引是大于這個字符串對應的char數(shù)組的長度拋出角標越界異常。index是從0開始到length-1結束。序列的第一個char值在索引0處,下一個在索引1處,依此類推,與數(shù)組索引一樣。

getChars方法

// srcBegin:要復制的字符串中第一個字符的索引【包含】。srcEnd:要復制的字符串中最后一個字符之后的索引【不包含】。dst[]:目標數(shù)組。dstBegin:目標數(shù)組中的起始偏移量。public void getChars(int srcBegin, int srcEnd, char dst[], int dstBegin) { // 校驗起始索引小于0拋出角標越界異常 if (srcBegin < 0) { throw new StringIndexOutOfBoundsException(srcBegin); } // 校驗結束索引大于原始字符串的長度拋出角標越界異常 if (srcEnd > value.length) { throw new StringIndexOutOfBoundsException(srcEnd); } // 校驗結束索引大于起始索引拋出角標越界異常 if (srcBegin > srcEnd) { throw new StringIndexOutOfBoundsException(srcEnd - srcBegin); } // 數(shù)組的拷貝 System.arraycopy(value, srcBegin, dst, dstBegin, srcEnd - srcBegin);}// 案例@Testpublic void test_string_codePointAt(){ // 原始字符串 String h = "ahelloworld"; // 目標char數(shù)組 char[] data = new char[4]; // 執(zhí)行拷貝 h.getChars(2, 6, data, 0); System.out.println(data);}

解析:將字符串中的字符復制到目標字符數(shù)組中。索引包含srcBegin,不包含srcEnd。

equals方法

// anObject:與此String進行比較的對象。public boolean equals(Object anObject) { // 引用相同直接返回true if (this == anObject) { return true; } // 判斷給定的對象是否是String類型的 if (anObject instanceof String) { // 給定的對象是字符串類型的轉換為字符串類型 String anotherString = (String)anObject; // 獲取當前字符串的長度 int n = value.length; // 判斷給定字符串的長度是否等于當前字符串的長度 if (n == anotherString.value.length) { // v1[]代表當前字符串對應的char數(shù)組 char v1[] = value; // v2[]代表給定的字符串對應的char數(shù)組 char v2[] = anotherString.value; // 遍歷原始char數(shù)組,并且與給定的字符串對應的數(shù)組進行比較 int i = 0; while (n-- != 0) { if (v1[i] != v2[i]) // 任意一個位置上不相等返回false return false; i++; } // 都相等返回true return true; } } // 不是String類型,或者長度不一致返回false return false;}

解析:這個方法重寫了Object中的equals方法。方法中的將此字符串與指定對象進行比較。接下來附贈一個手寫的String字符串equals方法。

手寫equals方法

private boolean mineEquals(String srcObject, Object anObject){ // 比較引用是否相同 if (srcObject == anObject){ return true; } // 引用不相同比較內容 if (anObject instanceof String){ String ans = (String) anObject; char[] srcChar = srcObject.toCharArray(); char[] anChar = ans.toCharArray(); int n = srcChar.length; if (n == anChar.length){ int i = 0; while (n-- != 0){ if (srcChar[i] != anChar[i]) return false; i++; } return true; } } return false;}// 測試我們自己寫的equals方法 @Test public void test_string_mine(){ String s = new String("aaa"); // 走的是引用的比較 System.out.println(s.equals(s));// true boolean b = mineEquals(s, s); System.out.println(b);// true }

equalsIgnoreCase方法

public boolean equalsIgnoreCase(String anotherString) { // 引用相同返回true。引用不相同進行長度、各個位置上的char是否相同 return (this == anotherString) ? true : (anotherString != null) && (anotherString.value.length == value.length) && regionMatches(true, 0, anotherString, 0, value.length);}

解析:將此字符串與另一個字符串進行比較,而忽略大小寫注意事項。regionMatches方法的源碼很有趣的,源碼里面有一個while循環(huán),先進行未忽略大小的判斷,然后進行忽略大小的判斷,在忽略大小的判斷中,先進行的是大寫的轉換進行比較,但是可能會失敗【這種字體Georgian alphabet】。所以在大寫轉換以后的比較失敗,進行一次小寫的轉換比較。

startsWith方法

// 判斷是否以指定的前綴開頭public boolean startsWith(String prefix) { // 0代表從開頭進行尋找 return startsWith(prefix, 0);}

endsWith方法

// 判斷是否以指定的前綴結尾public boolean endsWith(String suffix) { // 從【value.length - suffix.value.length】開始尋找,這個方法調用的還是startsWith方法 return startsWith(suffix, value.length - suffix.value.length);}

startsWith和endsWith最終的實現(xiàn)方法

// prefix: 測試此字符串是否以指定的前綴開頭。toffset: 從哪里開始尋找這個字符串。public boolean startsWith(String prefix, int toffset) { // 原始的字符串對應的char[] char ta[] = value; // 開始尋找的位置 int to = toffset; // 獲取指定的字符串對應的char[] char pa[] = prefix.value; int po = 0; // 獲取指定的字符串對應的char[]長度 int pc = prefix.value.length; // 開始尋找的位置小于0,或者起始位置大于要查找的長度【value.length - pc】返回false。 if ((toffset < 0) || (toffset > value.length - pc)) { return false; } // 比較給定的字符串的char[]里的每個元素是否跟原始的字符串對應的char數(shù)組的元素相同 while (--pc >= 0) { if (ta[to++] != pa[po++]) { // 有一個char不相同返回false return false; } } // 相同返回true return true;}

substring方法

// 返回一個字符串,該字符串是該字符串的子字符串。beginIndex開始截取的索引【包含】。public String substring(int beginIndex) { // 校驗指定的索引,小于0拋出角標越界 if (beginIndex < 0) { throw new StringIndexOutOfBoundsException(beginIndex); } // 子字符串的長度 int subLen = value.length - beginIndex; // 子字符串的長度小于0拋出角標越界 if (subLen < 0) { throw new StringIndexOutOfBoundsException(subLen); } // 開始位置為0,返回當前字符串,不為0,創(chuàng)建一個新的子字符串對象并返回 return (beginIndex == 0) ? this : new String(value, beginIndex, subLen);}

解析:返回一個字符串,該字符串是該字符串的子字符串。子字符串以指定索引處的字符開頭【包含】,并且擴展到該字符串的末尾。

substring方法

// beginIndex:開始位置【包含】。 endIndex:結束位置【不包含】。public String substring(int beginIndex, int endIndex) { // 校驗指定的開始索引,小于0拋出角標越界 if (beginIndex < 0) { throw new StringIndexOutOfBoundsException(beginIndex); } // 校驗指定的結束索引,大于給定的字符串的char數(shù)組的長度拋出角標越界 if (endIndex > value.length) { throw new StringIndexOutOfBoundsException(endIndex); } // 要截取的長度 int subLen = endIndex - beginIndex; // 要截取的長度小于0,拋出角標越界 if (subLen < 0) { throw new StringIndexOutOfBoundsException(subLen); } // 截取字符串 return ((beginIndex == 0) && (endIndex == value.length)) ? this : new String(value, beginIndex, subLen);}

解析:返回一個字符串,該字符串是該字符串的子字符串。子字符串從指定的beginIndex開始【包含】,并且擴展到索引endIndex-1處的字符【不包含】。

concat方法

public String concat(String str) { // 獲取給定的字符串的長度 int otherLen = str.length(); // 長度為0,直接返回當前的字符串 if (otherLen == 0) { return this; } // 獲取當前字符串的長度 int len = value.length; // 構建一個新的長度為len + otherLen的字符數(shù)組,并且將原始的數(shù)據(jù)放到這個數(shù)組 char buf[] = Arrays.copyOf(value, len + otherLen); // 這個底層調用是System.arraycopy這個方法的處理是使用c語言寫的 str.getChars(buf, len); return new String(buf, true);}

將指定的字符串連接到該字符串的末尾。字符串拼接。

format方法

// 使用指定的格式字符串和參數(shù)返回格式化的字符串。public static String format(String format, Object... args) { return new Formatter().format(format, args).toString();}// 案例,這里是使用%s替換后面的如"-a-"@Testpublic void test_start(){ System.out.println(String.format("ha %s hh %s a %s h", "-a-", "-b-", "-c-"));}

trim方法

public String trim() { // 指定字符串的長度 int len = value.length; // 定義一個開始位置的索引0 int st = 0; // 定義一個char[] val,用于避免使用getfiled操作碼,這個可以寫段代碼反編譯一下看看 char[] val = value; // 對于字符串的開頭進行去除空格,并記錄這個索引 while ((st < len) && (val[st] <= ' ')) { st++; } // 對于字符串的尾部進行去除空格,也記錄這個索引,這個索引就是去除尾部空格后的索引 while ((st < len) && (val[len - 1] <= ' ')) { len--; } // 根據(jù)上面記錄的長度判斷是否要截取字符串 return ((st > 0) || (len < value.length)) ? substring(st, len) : this;}

返回一個字符串,其值就是這個字符串,并去掉任何首部和尾部的空白。

join方法

// 返回一個新的String,該字符串由給定的分隔符和要連接的元素組成。delimiter:分隔每個元素的分隔符。elements:連接在一起的元素。public static String join(CharSequence delimiter, CharSequence... elements) { // delimiter和elements為空拋出空指針異常,null會被攔截,""不會被攔截 Objects.requireNonNull(delimiter); Objects.requireNonNull(elements); // StringJoiner joiner = new StringJoiner(delimiter); // 遍歷給定的要拼接的元素,拼接的元素允許為null for (CharSequence cs: elements) { // 執(zhí)行拼接方法 joiner.add(cs); } return joiner.toString();}// 拼接方法public StringJoiner add(CharSequence newElement) { // prepareBuilder()方法首次調用會創(chuàng)建StringBuilder對象,后面再調用會執(zhí)行拼接分隔符 prepareBuilder().append(newElement); return this;}// 未進行拼接創(chuàng)建StringBuilder對象,已經(jīng)拼接以后value != null執(zhí)行拼接分隔符private StringBuilder prepareBuilder() { // 判斷拼接的value是否為空 if (value != null) { // 不為空執(zhí)行拼接分隔符 value.append(delimiter); } else { // 最開始使用拼接的時候,調用這個方法創(chuàng)建一個空的StringBuilder對象,只調一次 value = new StringBuilder().append(prefix); } return value;}// 上面是調用的這個拼接元素方法@Overridepublic StringBuilder append(CharSequence s) { // 這里啥都沒處理,調用的是父類的append方法,設計模式為建造者模式 super.append(s); return this;}// 上面的prepareBuilder方法是拼接分隔符,這個方法是將分隔符和給定的元素拼接的方法@Overridepublic AbstractStringBuilder append(CharSequence s) { // 以下3個判斷根據(jù)類型和是否為空進行區(qū)別拼接 if (s == null) return appendNull(); if (s instanceof String) return this.append((String)s); if (s instanceof AbstractStringBuilder) return this.append((AbstractStringBuilder)s); // 拼接 return this.append(s, 0, s.length());}

將給定的字符串以給定的分割符分割并返回分隔后的字符串。

replace方法

// target:要被替換的目標字符串。 replacement:替換的字符串public String replace(CharSequence target, CharSequence replacement) { return Pattern.compile(target.toString(), Pattern.LITERAL).matcher( this).replaceAll(Matcher.quoteReplacement(replacement.toString()));}

解析:用指定的字符串替換這個字符串中與之匹配的每個子字符串。替換從字符串的開頭到結尾,例如,在字符串 "aaa "中用 "b "替換 "aa "將導致 "ba "而不是 "ab"。

replaceAll方法

// regex:這個支持正則表達式,也可以是要被替換的目標字符串。public String replaceAll(String regex, String replacement) { return Pattern.compile(regex).matcher(this).replaceAll(replacement);}

問題:replace和replaceAll方法的區(qū)別是啥?

replaceAll支持正則表達式。

針對char的replace方法

// oldChar:要被替換的字符,newChar:替換的字符public String replace(char oldChar, char newChar) { // oldChar不等于newChar if (oldChar != newChar) { // 當前字符串的長度 int len = value.length; // 這個用于下面的while循環(huán)里的條件比較,val[i]中的i是從0開始的 int i = -1; // 定義一個char[] val,用于避免使用getfiled操作碼,這個可以寫段代碼反編譯一下看看 char[] val = value; /* avoid getfield opcode */ // 這個用于記錄這個i的值,并且判斷是否有要替換的,這個循環(huán)有利于性能的提升 while (++i < len) { // val[i]中的i是從0開始的 if (val[i] == oldChar) { // 有要替換的直接跳出循環(huán) break; } } // 上面的while循環(huán)中如果有要替換的i肯定小于len,如果沒有下面這個判斷就不會執(zhí)行 if (i < len) { // 能進到這個循環(huán)肯定是有要替換的,創(chuàng)建一個長度為len的char數(shù)組 char buf[] = new char[len]; // 上面的i是記錄第一個可以替換的char的索引,下面這個循環(huán)是將這個i索引前的不需要被替換的填充到buf[]數(shù)組中 for (int j = 0; j < i; j++) { // 填充buf[]數(shù)組 buf[j] = val[j]; } // 從可以替換的索引i開始將剩余的字符一個一個填充到 buf[]中 while (i < len) { // 獲取要被替換的字符 char c = val[i]; // 判斷這個字符是否真的需要替換,c == oldChar成立就替換,否則不替換 buf[i] = (c == oldChar) ? newChar : c; i++; } // 返回替換后的字符串 return new String(buf, true); } } // oldChar等于newChar直接返回當前字符串 return this;}

案例

@Testpublic void test_matches(){ String a = "adddfdefe"; System.out.println(a.replace('d', 'b'));// abbbfbefe}仿寫replace方法參數(shù)針對char

仿寫

// 和源碼給的唯一不同的是參數(shù)傳遞,其他的都和源碼一樣,自己寫一遍可以加深記憶和借鑒編程思public String replace(String source, char oldChar, char newChar) { char[] value = source.toCharArray(); if (oldChar != newChar) { int len = value.length; int i = -1; char[] val = value; /* avoid getfield opcode */ while (++i < len) { if (val[i] == oldChar) { break; } } if (i < len) { char buf[] = new char[len]; for (int j = 0; j < i; j++) { buf[j] = val[j]; } while (i < len) { char c = val[i]; buf[i] = (c == oldChar) ? newChar : c; i++; } return new String(buf); } } return new String(value);}

intern方法

public native String intern();

這是一個native方法。調用String#intern方法時,如果池中已經(jīng)包含一個由equals方法確定的等于此String對象的字符串,則返回來自池的字符串。否則,將此String對象添加到池中,并返回這個String的引用。


分享

上面是本人在學習路上整理的一些比較干貨的java資料,如果有需要的兄弟可以先關注我,私信我回復【資料】即可。

總結

以上是生活随笔為你收集整理的java的map 使用string数组多了双引号_奥奥奥利给!!!再也不怕面试官问我String源码了!来吧...的全部內容,希望文章能夠幫你解決所遇到的問題。

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

主站蜘蛛池模板: 国产熟女高潮视频 | 亚洲精品视频一二三区 | 免费的a级片 | 欧美一区二区影院 | 狠狠干av| www.色就是色| 免费网站在线观看视频 | 日本熟妇成熟毛茸茸 | 日批在线观看视频 | 亚洲国产欧美在线人成 | 黄色午夜影院 | av资源在线看 | 高清在线一区二区 | 国产a级免费视频 | 久久福利社 | 一区二区成人av | 99热在线免费观看 | 四虎影酷 | 探花视频在线免费观看 | 国产精品老熟女视频一区二区 | 久久永久免费 | 国内三级视频 | 少妇2做爰hd韩国电影 | 欧美v亚洲 | 黄色在线免费看 | www.xxxxx日本| 台湾综合色 | 131美女爱做视频 | 在线看a网站 | 麻豆av在线免费观看 | 精品乱码一区内射人妻无码 | 天天爽影院 | 亚洲一卡二卡 | 久久久久夜 | 中文无码日韩欧 | 国产96在线| 网友自拍第一页 | 国产成人区 | 欧美伦理影院 | 羞羞影院体验区 | 99久久久无码国产精品免费麻豆 | 天天草av| 荷兰女人裸体性做爰 | av作品在线观看 | 婷婷四月 | 粉嫩av四季av绯色av | 污污的网站在线观看 | 亚洲日本japanese丝袜 | 欧美射射射| aa视频在线 | 97超碰成人 | 伊人亚洲 | 日韩欧美一 | 国产成人97精品免费看片 | 日日爽夜夜爽 | 久草久操| 在线a毛片| 色老头一区 | 精品国产免费av | 久久高清免费 | 95视频在线| 日韩 国产 在线 | 老妇女玩小男生毛片 | 亚洲少妇中文字幕 | 欧美成人aaa | 亚洲视频一二 | 欧美成年人 | www日本在线 | 国产91丝袜在线播放九色 | 欧美日韩在线免费视频 | 久久av一区二区三区亚洲 | 超碰在线中文字幕 | videosex抽搐痉挛高潮 | 国产精品免费一区二区三区都可以 | 欧美激情亚洲综合 | 日本成人毛片 | 四虎影裤| 日本亚洲色大成网站www久久 | 欧洲日韩一区二区三区 | 亚洲精品一线 | 久久久久久久久久电影 | 男女xx网站| 黄色网址进入 | 国产性猛交96 | 亚洲无色 | 精品少妇一区二区三区免费观看 | 欧美在线观看一区二区三区 | 亚洲国产日韩欧美在线观看 | 黄视频国产 | a级片免费在线观看 | 亚洲成人少妇 | 精品国产av一区二区 | 免费在线观看网址入口 | 九九色精品 | 蜜臀av中文字幕 | 91麻豆成人精品国产免费网站 | xxxxhdvideos | av片免费看 | 双性皇帝高h喷汁呻吟 |