3atv精品不卡视频,97人人超碰国产精品最新,中文字幕av一区二区三区人妻少妇,久久久精品波多野结衣,日韩一区二区三区精品

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

[转载] Java面试题全集(上)

發布時間:2025/3/11 java 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 [转载] Java面试题全集(上) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

參考鏈接: 如何運行不同目錄中的Java類文件

2013年年底的時候,我看到了網上流傳的一個叫做《Java面試題大全》的東西,認真的閱讀了以后發現里面的很多題目是重復且沒有價值的題目,還有不少的參考答案也是錯誤的,于是我花了半個月時間對這個所謂的《Java面試大全》進行了全面的修訂并重新發布在我的CSDN博客。在修訂的過程中,參照了當時JDK最新版本(Java 7)給出了題目的答案和相關代碼,去掉了EJB 2.x、JSF等無用內容或過時內容,補充了數據結構和算法、大型網站技術架構、設計模式、UML、Spring MVC等內容并對很多知識點進行了深入的剖析,例如hashCode方法的設計、垃圾收集、并發編程、數據庫事務等。當時我甚至希望把面試中經常出現的操作系統、數據庫、軟件測試等內容也補充進去,但是由于各種原因,最終只整理出了150道面試題。讓我欣慰的是,這150道題還是幫助到了很多人,而且在我CSDN博客上的總訪問量超過了5萬次,最終還被很多網站和個人以原創的方式轉載了。最近一年內,用百度搜索"Java面試"我寫的這些東西基本上都排在搜索結果的前5名,這讓我覺得"亞歷山大",因為我寫的這些東西一旦不準確就可能誤導很多人。2014年的時候我又整理了30道題,希望把之前遺漏的面試題和知識點補充上去,但是仍然感覺掛一漏萬,而且Java 8問世后很多新的東西又需要去總結和整理。為此,我不止一次的修改了之前的180題,修改到自己已經感覺有些疲憊或者厭煩了。2014年至今,自己帶的學生又有很多走上了Java程序員、Java工程師的工作崗位,他們的面試經驗也還沒來得及跟大家分享,冥冥之中似乎有一股力量在刺激我要重新寫一篇《Java面試題全集》,于是這篇文章就誕生了。請不要責備我把那些出現過的內容又寫了一次,因為每次寫東西就算是重復的內容,我也需要對編程語言和相關技術進行重新思考,不僅字斟句酌更是力求至臻完美,所以請相信我分享的一定是更新的、更好的、更有益的東西,這些內容也訴說著一個職業程序員和培訓師的思想、精神和情感。?

1、面向對象的特征有哪些方面?? 答:面向對象的特征主要有以下幾個方面:? - 抽象:抽象是將一類對象的共同特征總結出來構造類的過程,包括數據抽象和行為抽象兩方面。抽象只關注對象有哪些屬性和行為,并不關注這些行為的細節是什么。? - 繼承:繼承是從已有類得到繼承信息創建新類的過程。提供繼承信息的類被稱為父類(超類、基類);得到繼承信息的類被稱為子類(派生類)。繼承讓變化中的軟件系統有了一定的延續性,同時繼承也是封裝程序中可變因素的重要手段(如果不能理解請閱讀閻宏博士的《Java與模式》或《設計模式精解》中關于橋梁模式的部分)。? - 封裝:通常認為封裝是把數據和操作數據的方法綁定起來,對數據的訪問只能通過已定義的接口。面向對象的本質就是將現實世界描繪成一系列完全自治、封閉的對象。我們在類中編寫的方法就是對實現細節的一種封裝;我們編寫一個類就是對數據和數據操作的封裝。可以說,封裝就是隱藏一切可隱藏的東西,只向外界提供最簡單的編程接口(可以想想普通洗衣機和全自動洗衣機的差別,明顯全自動洗衣機封裝更好因此操作起來更簡單;我們現在使用的智能手機也是封裝得足夠好的,因為幾個按鍵就搞定了所有的事情)。? - 多態性:多態性是指允許不同子類型的對象對同一消息作出不同的響應。簡單的說就是用同樣的對象引用調用同樣的方法但是做了不同的事情。多態性分為編譯時的多態性和運行時的多態性。如果將對象的方法視為對象向外界提供的服務,那么運行時的多態性可以解釋為:當A系統訪問B系統提供的服務時,B系統有多種提供服務的方式,但一切對A系統來說都是透明的(就像電動剃須刀是A系統,它的供電系統是B系統,B系統可以使用電池供電或者用交流電,甚至還有可能是太陽能,A系統只會通過B類對象調用供電的方法,但并不知道供電系統的底層實現是什么,究竟通過何種方式獲得了動力)。方法重載(overload)實現的是編譯時的多態性(也稱為前綁定),而方法重寫(override)實現的是運行時的多態性(也稱為后綁定)。運行時的多態是面向對象最精髓的東西,要實現多態需要做兩件事:1). 方法重寫(子類繼承父類并重寫父類中已有的或抽象的方法);2). 對象造型(用父類型引用引用子類型對象,這樣同樣的引用調用同樣的方法就會根據子類對象的不同而表現出不同的行為)。?

2、訪問修飾符public,private,protected,以及不寫(默認)時的區別?? 答:?

修飾符當前類同 包子 類其他包public√√√√protected√√√×default√√××private√×××?

類的成員不寫訪問修飾時默認為default。默認對于同一個包中的其他類相當于公開(public),對于不是同一個包中的其他類相當于私有(private)。受保護(protected)對子類相當于公開,對不是同一包中的沒有父子關系的類相當于私有。Java中,外部類的修飾符只能是public或默認,類的成員(包括內部類)的修飾符可以是以上四種。?

3、String 是最基本的數據類型嗎?? 答:不是。Java中的基本數據類型只有8個:byte、short、int、long、float、double、char、boolean;除了基本類型(primitive type),剩下的都是引用類型(reference type),Java 5以后引入的枚舉類型也算是一種比較特殊的引用類型。?

4、float f=3.4;是否正確?? 答:不正確。3.4是雙精度數,將雙精度型(double)賦值給浮點型(float)屬于下轉型(down-casting,也稱為窄化)會造成精度損失,因此需要強制類型轉換float f =(float)3.4; 或者寫成float f =3.4F;。?

5、short s1 = 1; s1 = s1 + 1;有錯嗎?short s1 = 1; s1 += 1;有錯嗎?? 答:對于short s1 = 1; s1 = s1 + 1;由于1是int類型,因此s1+1運算結果也是int 型,需要強制轉換類型才能賦值給short型。而short s1 = 1; s1 += 1;可以正確編譯,因為s1+= 1;相當于s1 = (short)(s1 + 1);其中有隱含的強制類型轉換。?

6、Java有沒有goto?? 答:goto 是Java中的保留字,在目前版本的Java中沒有使用。(根據James Gosling(Java之父)編寫的《The Java Programming Language》一書的附錄中給出了一個Java關鍵字列表,其中有goto和const,但是這兩個是目前無法使用的關鍵字,因此有些地方將其稱之為保留字,其實保留字這個詞應該有更廣泛的意義,因為熟悉C語言的程序員都知道,在系統類庫中使用過的有特殊意義的單詞或單詞的組合都被視為保留字)?

7、int和Integer有什么區別?? 答:Java是一個近乎純潔的面向對象編程語言,但是為了編程的方便還是引入了基本數據類型,但是為了能夠將這些基本數據類型當成對象操作,Java為每一個基本數據類型都引入了對應的包裝類型(wrapper class),int的包裝類就是Integer,從Java 5開始引入了自動裝箱/拆箱機制,使得二者可以相互轉換。? Java 為每個原始類型提供了包裝類型:? - 原始類型: boolean,char,byte,short,int,long,float,double? - 包裝類型:Boolean,Character,Byte,Short,Integer,Long,Float,Double?

class AutoUnboxingTest {

?

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

? ? ? ? Integer a = new Integer(3);

? ? ? ? Integer b = 3;? ? ? ? ? ? ? ? ? // 將3自動裝箱成Integer類型

? ? ? ? int c = 3;

? ? ? ? System.out.println(a == b);? ? ?// false 兩個引用沒有引用同一對象

? ? ? ? System.out.println(a == c);? ? ?// true a自動拆箱成int類型再和c比較

? ? }

}?

最近還遇到一個面試題,也是和自動裝箱和拆箱有點關系的,代碼如下所示:?

public class Test03 {

?

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

? ? ? ? Integer f1 = 100, f2 = 100, f3 = 150, f4 = 150;

?

? ? ? ? System.out.println(f1 == f2);

? ? ? ? System.out.println(f3 == f4);

? ? }

}?

如果不明就里很容易認為兩個輸出要么都是true要么都是false。首先需要注意的是f1、f2、f3、f4四個變量都是Integer對象引用,所以下面的==運算比較的不是值而是引用。裝箱的本質是什么呢?當我們給一個Integer對象賦一個int值的時候,會調用Integer類的靜態方法valueOf,如果看看valueOf的源代碼就知道發生了什么。?

? ? public static Integer valueOf(int i) {

? ? ? ? if (i >= IntegerCache.low && i <= IntegerCache.high)

? ? ? ? ? ? return IntegerCache.cache[i + (-IntegerCache.low)];

? ? ? ? return new Integer(i);

? ? }?

IntegerCache是Integer的內部類,其代碼如下所示:?

/**

? ? ?* Cache to support the object identity semantics of autoboxing for values between

? ? ?* -128 and 127 (inclusive) as required by JLS.

? ? ?*

? ? ?* The cache is initialized on first usage.? The size of the cache

? ? ?* may be controlled by the {@code -XX:AutoBoxCacheMax=<size>} option.

? ? ?* During VM initialization, java.lang.Integer.IntegerCache.high property

? ? ?* may be set and saved in the private system properties in the

? ? ?* sun.misc.VM class.

? ? ?*/

?

? ? private static class IntegerCache {

? ? ? ? static final int low = -128;

? ? ? ? static final int high;

? ? ? ? static final Integer cache[];

?

? ? ? ? static {

? ? ? ? ? ? // high value may be configured by property

? ? ? ? ? ? int h = 127;

? ? ? ? ? ? String integerCacheHighPropValue =

? ? ? ? ? ? ? ? sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");

? ? ? ? ? ? if (integerCacheHighPropValue != null) {

? ? ? ? ? ? ? ? try {

? ? ? ? ? ? ? ? ? ? int i = parseInt(integerCacheHighPropValue);

? ? ? ? ? ? ? ? ? ? i = Math.max(i, 127);

? ? ? ? ? ? ? ? ? ? // Maximum array size is Integer.MAX_VALUE

? ? ? ? ? ? ? ? ? ? h = Math.min(i, Integer.MAX_VALUE - (-low) -1);

? ? ? ? ? ? ? ? } catch( NumberFormatException nfe) {

? ? ? ? ? ? ? ? ? ? // If the property cannot be parsed into an int, ignore it.

? ? ? ? ? ? ? ? }

? ? ? ? ? ? }

? ? ? ? ? ? high = h;

?

? ? ? ? ? ? cache = new Integer[(high - low) + 1];

? ? ? ? ? ? int j = low;

? ? ? ? ? ? for(int k = 0; k < cache.length; k++)

? ? ? ? ? ? ? ? cache[k] = new Integer(j++);

?

? ? ? ? ? ? // range [-128, 127] must be interned (JLS7 5.1.7)

? ? ? ? ? ? assert IntegerCache.high >= 127;

? ? ? ? }

?

? ? ? ? private IntegerCache() {}

? ? }?

簡單的說,如果整型字面量的值在-128到127之間,那么不會new新的Integer對象,而是直接引用常量池中的Integer對象,所以上面的面試題中f1==f2的結果是true,而f3==f4的結果是false。?

?

?提醒:越是貌似簡單的面試題其中的玄機就越多,需要面試者有相當深厚的功力。?

?

8、&和&&的區別?? 答:&運算符有兩種用法:(1)按位與;(2)邏輯與。&&運算符是短路與運算。邏輯與跟短路與的差別是非常巨大的,雖然二者都要求運算符左右兩端的布爾值都是true整個表達式的值才是true。&&之所以稱為短路運算是因為,如果&&左邊的表達式的值是false,右邊的表達式會被直接短路掉,不會進行運算。很多時候我們可能都需要用&&而不是&,例如在驗證用戶登錄時判定用戶名不是null而且不是空字符串,應當寫為:username != null &&!username.equals(""),二者的順序不能交換,更不能用&運算符,因為第一個條件如果不成立,根本不能進行字符串的equals比較,否則會產生NullPointerException異常。注意:邏輯或運算符(|)和短路或運算符(||)的差別也是如此。?

?

?補充:如果你熟悉JavaScript,那你可能更能感受到短路運算的強大,想成為JavaScript的高手就先從玩轉短路運算開始吧。?

?

9、解釋內存中的棧(stack)、堆(heap)和方法區(method area)的用法。? 答:通常我們定義一個基本數據類型的變量,一個對象的引用,還有就是函數調用的現場保存都使用JVM中的棧空間;而通過new關鍵字和構造器創建的對象則放在堆空間,堆是垃圾收集器管理的主要區域,由于現在的垃圾收集器都采用分代收集算法,所以堆空間還可以細分為新生代和老生代,再具體一點可以分為Eden、Survivor(又可分為From Survivor和To Survivor)、Tenured;方法區和堆都是各個線程共享的內存區域,用于存儲已經被JVM加載的類信息、常量、靜態變量、JIT編譯器編譯后的代碼等數據;程序中的字面量(literal)如直接書寫的100、"hello"和常量都是放在常量池中,常量池是方法區的一部分,。棧空間操作起來最快但是棧很小,通常大量的對象都是放在堆空間,棧和堆的大小都可以通過JVM的啟動參數來進行調整,棧空間用光了會引發StackOverflowError,而堆和常量池空間不足則會引發OutOfMemoryError。?

String str = new String("hello");?

上面的語句中變量str放在棧上,用new創建出來的字符串對象放在堆上,而"hello"這個字面量是放在方法區的。?

?

?補充1:較新版本的Java(從Java 6的某個更新開始)中,由于JIT編譯器的發展和"逃逸分析"技術的逐漸成熟,棧上分配、標量替換等優化技術使得對象一定分配在堆上這件事情已經變得不那么絕對了。?

?補充2:運行時常量池相當于Class文件常量池具有動態性,Java語言并不要求常量一定只有編譯期間才能產生,運行期間也可以將新的常量放入池中,String類的intern()方法就是這樣的。?

?

看看下面代碼的執行結果是什么并且比較一下Java 7以前和以后的運行結果是否一致。?

String s1 = new StringBuilder("go")

? ? .append("od").toString();

System.out.println(s1.intern() == s1);

String s2 = new StringBuilder("ja")

? ? .append("va").toString();

System.out.println(s2.intern() == s2);?

10、Math.round(11.5) 等于多少?Math.round(-11.5)等于多少?? 答:Math.round(11.5)的返回值是12,Math.round(-11.5)的返回值是-11。四舍五入的原理是在參數上加0.5然后進行下取整。?

11、switch 是否能作用在byte 上,是否能作用在long 上,是否能作用在String上?? 答:在Java 5以前,switch(expr)中,expr只能是byte、short、char、int。從Java 5開始,Java中引入了枚舉類型,expr也可以是enum類型,從Java 7開始,expr還可以是字符串(String),但是長整型(long)在目前所有的版本中都是不可以的。?

12、用最有效率的方法計算2乘以8?? 答: 2 << 3(左移3位相當于乘以2的3次方,右移3位相當于除以2的3次方)。?

?

?補充:我們為編寫的類重寫hashCode方法時,可能會看到如下所示的代碼,其實我們不太理解為什么要使用這樣的乘法運算來產生哈希碼(散列碼),而且為什么這個數是個素數,為什么通常選擇31這個數?前兩個問題的答案你可以自己百度一下,選擇31是因為可以用移位和減法運算來代替乘法,從而得到更好的性能。說到這里你可能已經想到了:31 * num 等價于(num << 5) - num,左移5位相當于乘以2的5次方再減去自身就相當于乘以31,現在的VM都能自動完成這個優化。?

?

public class PhoneNumber {

? ? private int areaCode;

? ? private String prefix;

? ? private String lineNumber;

?

? ? @Override

? ? public int hashCode() {

? ? ? ? final int prime = 31;

? ? ? ? int result = 1;

? ? ? ? result = prime * result + areaCode;

? ? ? ? result = prime * result

? ? ? ? ? ? ? ? + ((lineNumber == null) ? 0 : lineNumber.hashCode());

? ? ? ? result = prime * result + ((prefix == null) ? 0 : prefix.hashCode());

? ? ? ? return result;

? ? }

?

? ? @Override

? ? public boolean equals(Object obj) {

? ? ? ? if (this == obj)

? ? ? ? ? ? return true;

? ? ? ? if (obj == null)

? ? ? ? ? ? return false;

? ? ? ? if (getClass() != obj.getClass())

? ? ? ? ? ? return false;

? ? ? ? PhoneNumber other = (PhoneNumber) obj;

? ? ? ? if (areaCode != other.areaCode)

? ? ? ? ? ? return false;

? ? ? ? if (lineNumber == null) {

? ? ? ? ? ? if (other.lineNumber != null)

? ? ? ? ? ? ? ? return false;

? ? ? ? } else if (!lineNumber.equals(other.lineNumber))

? ? ? ? ? ? return false;

? ? ? ? if (prefix == null) {

? ? ? ? ? ? if (other.prefix != null)

? ? ? ? ? ? ? ? return false;

? ? ? ? } else if (!prefix.equals(other.prefix))

? ? ? ? ? ? return false;

? ? ? ? return true;

? ? }

?

}?

13、數組有沒有length()方法?String有沒有length()方法?? 答:數組沒有length()方法,有length 的屬性。String 有length()方法。JavaScript中,獲得字符串的長度是通過length屬性得到的,這一點容易和Java混淆。?

14、在Java中,如何跳出當前的多重嵌套循環?? 答:在最外層循環前加一個標記如A,然后用break A;可以跳出多重循環。(Java中支持帶標簽的break和continue語句,作用有點類似于C和C++中的goto語句,但是就像要避免使用goto一樣,應該避免使用帶標簽的break和continue,因為它不會讓你的程序變得更優雅,很多時候甚至有相反的作用,所以這種語法其實不知道更好)?

15、構造器(constructor)是否可被重寫(override)?? 答:構造器不能被繼承,因此不能被重寫,但可以被重載。?

16、兩個對象值相同(x.equals(y) == true),但卻可有不同的hash code,這句話對不對?? 答:不對,如果兩個對象x和y滿足x.equals(y) == true,它們的哈希碼(hash code)應當相同。Java對于eqauls方法和hashCode方法是這樣規定的:(1)如果兩個對象相同(equals方法返回true),那么它們的hashCode值一定要相同;(2)如果兩個對象的hashCode相同,它們并不一定相同。當然,你未必要按照要求去做,但是如果你違背了上述原則就會發現在使用容器時,相同的對象可以出現在Set集合中,同時增加新元素的效率會大大下降(對于使用哈希存儲的系統,如果哈希碼頻繁的沖突將會造成存取性能急劇下降)。?

?

?補充:關于equals和hashCode方法,很多Java程序都知道,但很多人也就是僅僅知道而已,在Joshua Bloch的大作《Effective Java》(很多軟件公司,《Effective Java》、《Java編程思想》以及《重構:改善既有代碼質量》是Java程序員必看書籍,如果你還沒看過,那就趕緊去亞馬遜買一本吧)中是這樣介紹equals方法的:首先equals方法必須滿足自反性(x.equals(x)必須返回true)、對稱性(x.equals(y)返回true時,y.equals(x)也必須返回true)、傳遞性(x.equals(y)和y.equals(z)都返回true時,x.equals(z)也必須返回true)和一致性(當x和y引用的對象信息沒有被修改時,多次調用x.equals(y)應該得到同樣的返回值),而且對于任何非null值的引用x,x.equals(null)必須返回false。實現高質量的equals方法的訣竅包括:1. 使用==操作符檢查"參數是否為這個對象的引用";2. 使用instanceof操作符檢查"參數是否為正確的類型";3. 對于類中的關鍵屬性,檢查參數傳入對象的屬性是否與之相匹配;4. 編寫完equals方法后,問自己它是否滿足對稱性、傳遞性、一致性;5. 重寫equals時總是要重寫hashCode;6. 不要將equals方法參數中的Object對象替換為其他的類型,在重寫時不要忘掉@Override注解。?

?

17、是否可以繼承String類?? 答:String 類是final類,不可以被繼承。?

?

?補充:繼承String本身就是一個錯誤的行為,對String類型最好的重用方式是關聯關系(Has-A)和依賴關系(Use-A)而不是繼承關系(Is-A)。?

?

18、當一個對象被當作參數傳遞到一個方法后,此方法可改變這個對象的屬性,并可返回變化后的結果,那么這里到底是值傳遞還是引用傳遞?? 答:是值傳遞。Java語言的方法調用只支持參數的值傳遞。當一個對象實例作為一個參數被傳遞到方法中時,參數的值就是對該對象的引用。對象的屬性可以在被調用過程中被改變,但對對象引用的改變是不會影響到調用者的。C++和C#中可以通過傳引用或傳輸出參數來改變傳入的參數的值。在C#中可以編寫如下所示的代碼,但是在Java中卻做不到。?

using System;

?

namespace CS01 {

?

? ? class Program {

? ? ? ? public static void swap(ref int x, ref int y) {

? ? ? ? ? ? int temp = x;

? ? ? ? ? ? x = y;

? ? ? ? ? ? y = temp;

? ? ? ? }

?

? ? ? ? public static void Main (string[] args) {

? ? ? ? ? ? int a = 5, b = 10;

? ? ? ? ? ? swap (ref a, ref b);

? ? ? ? ? ? // a = 10, b = 5;

? ? ? ? ? ? Console.WriteLine ("a = {0}, b = {1}", a, b);

? ? ? ? }

? ? }

}?

?

?說明:Java中沒有傳引用實在是非常的不方便,這一點在Java 8中仍然沒有得到改進,正是如此在Java編寫的代碼中才會出現大量的Wrapper類(將需要通過方法調用修改的引用置于一個Wrapper類中,再將Wrapper對象傳入方法),這樣的做法只會讓代碼變得臃腫,尤其是讓從C和C++轉型為Java程序員的開發者無法容忍。?

?

19、String和StringBuilder、StringBuffer的區別?? 答:Java平臺提供了兩種類型的字符串:String和StringBuffer/StringBuilder,它們可以儲存和操作字符串。其中String是只讀字符串,也就意味著String引用的字符串內容是不能被改變的。而StringBuffer/StringBuilder類表示的字符串對象可以直接進行修改。StringBuilder是Java 5中引入的,它和StringBuffer的方法完全相同,區別在于它是在單線程環境下使用的,因為它的所有方面都沒有被synchronized修飾,因此它的效率也比StringBuffer要高。?

?

?面試題1 - 什么情況下用+運算符進行字符串連接比調用StringBuffer/StringBuilder對象的append方法連接字符串性能更好??

?面試題2 - 請說出下面程序的輸出。?

?

class StringEqualTest {

?

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

? ? ? ? String s1 = "Programming";

? ? ? ? String s2 = new String("Programming");

? ? ? ? String s3 = "Program";

? ? ? ? String s4 = "ming";

? ? ? ? String s5 = "Program" + "ming";

? ? ? ? String s6 = s3 + s4;

? ? ? ? System.out.println(s1 == s2);

? ? ? ? System.out.println(s1 == s5);

? ? ? ? System.out.println(s1 == s6);

? ? ? ? System.out.println(s1 == s6.intern());

? ? ? ? System.out.println(s2 == s2.intern());

? ? }

}?

?

?補充:解答上面的面試題需要清除兩點:1. String對象的intern方法會得到字符串對象在常量池中對應的版本的引用(如果常量池中有一個字符串與String對象的equals結果是true),如果常量池中沒有對應的字符串,則該字符串將被添加到常量池中,然后返回常量池中字符串的引用;2. 字符串的+操作其本質是創建了StringBuilder對象進行append操作,然后將拼接后的StringBuilder對象用toString方法處理成String對象,這一點可以用javap -c StringEqualTest.class命令獲得class文件對應的JVM字節碼指令就可以看出來。??

?

20、重載(Overload)和重寫(Override)的區別。重載的方法能否根據返回類型進行區分?? 答:方法的重載和重寫都是實現多態的方式,區別在于前者實現的是編譯時的多態性,而后者實現的是運行時的多態性。重載發生在一個類中,同名的方法如果有不同的參數列表(參數類型不同、參數個數不同或者二者都不同)則視為重載;重寫發生在子類與父類之間,重寫要求子類被重寫方法與父類被重寫方法有相同的返回類型,比父類被重寫方法更好訪問,不能比父類被重寫方法聲明更多的異常(里氏代換原則)。重載對返回類型沒有特殊的要求。?

?

?面試題:華為的面試題中曾經問過這樣一個問題 - "為什么不能根據返回類型來區分重載",快說出你的答案吧!?

?

21、描述一下JVM加載class文件的原理機制?? 答:JVM中類的裝載是由類加載器(ClassLoader)和它的子類來實現的,Java中的類加載器是一個重要的Java運行時系統組件,它負責在運行時查找和裝入類文件中的類。? 由于Java的跨平臺性,經過編譯的Java源程序并不是一個可執行程序,而是一個或多個類文件。當Java程序需要使用某個類時,JVM會確保這個類已經被加載、連接(驗證、準備和解析)和初始化。類的加載是指把類的.class文件中的數據讀入到內存中,通常是創建一個字節數組讀入.class文件,然后產生與所加載類對應的Class對象。加載完成后,Class對象還不完整,所以此時的類還不可用。當類被加載后就進入連接階段,這一階段包括驗證、準備(為靜態變量分配內存并設置默認的初始值)和解析(將符號引用替換為直接引用)三個步驟。最后JVM對類進行初始化,包括:1)如果類存在直接的父類并且這個類還沒有被初始化,那么就先初始化父類;2)如果類中存在初始化語句,就依次執行這些初始化語句。? 類的加載是由類加載器完成的,類加載器包括:根加載器(BootStrap)、擴展加載器(Extension)、系統加載器(System)和用戶自定義類加載器(java.lang.ClassLoader的子類)。從Java 2(JDK 1.2)開始,類加載過程采取了父親委托機制(PDM)。PDM更好的保證了Java平臺的安全性,在該機制中,JVM自帶的Bootstrap是根加載器,其他的加載器都有且僅有一個父類加載器。類的加載首先請求父類加載器加載,父類加載器無能為力時才由其子類加載器自行加載。JVM不會向Java程序提供對Bootstrap的引用。下面是關于幾個類加載器的說明:?

?

?Bootstrap:一般用本地代碼實現,負責加載JVM基礎核心類庫(rt.jar);Extension:從java.ext.dirs系統屬性所指定的目錄中加載類庫,它的父加載器是Bootstrap;System:又叫應用類加載器,其父類是Extension。它是應用最廣泛的類加載器。它從環境變量classpath或者系統屬性java.class.path所指定的目錄中記載類,是用戶自定義加載器的默認父加載器。?

?

22、char 型變量中能不能存貯一個中文漢字,為什么?? 答:char類型可以存儲一個中文漢字,因為Java中使用的編碼是Unicode(不選擇任何特定的編碼,直接使用字符在字符集中的編號,這是統一的唯一方法),一個char類型占2個字節(16比特),所以放一個中文是沒問題的。?

?

?補充:使用Unicode意味著字符在JVM內部和外部有不同的表現形式,在JVM內部都是Unicode,當這個字符被從JVM內部轉移到外部時(例如存入文件系統中),需要進行編碼轉換。所以Java中有字節流和字符流,以及在字符流和字節流之間進行轉換的轉換流,如InputStreamReader和OutputStreamReader,這兩個類是字節流和字符流之間的適配器類,承擔了編碼轉換的任務;對于C程序員來說,要完成這樣的編碼轉換恐怕要依賴于union(聯合體/共用體)共享內存的特征來實現了。?

?

23、抽象類(abstract class)和接口(interface)有什么異同?? 答:抽象類和接口都不能夠實例化,但可以定義抽象類和接口類型的引用。一個類如果繼承了某個抽象類或者實現了某個接口都需要對其中的抽象方法全部進行實現,否則該類仍然需要被聲明為抽象類。接口比抽象類更加抽象,因為抽象類中可以定義構造器,可以有抽象方法和具體方法,而接口中不能定義構造器而且其中的方法全部都是抽象方法。抽象類中的成員可以是private、默認、protected、public的,而接口中的成員全都是public的。抽象類中可以定義成員變量,而接口中定義的成員變量實際上都是常量。有抽象方法的類必須被聲明為抽象類,而抽象類未必要有抽象方法。?

24、靜態嵌套類(Static Nested Class)和內部類(Inner Class)的不同?? 答:Static Nested Class是被聲明為靜態(static)的內部類,它可以不依賴于外部類實例被實例化。而通常的內部類需要在外部類實例化后才能實例化,其語法看起來挺詭異的,如下所示。?

/**

?* 撲克類(一副撲克)

?* @author 駱昊

?*

?*/

public class Poker {

? ? private static String[] suites = {"黑桃", "紅桃", "草花", "方塊"};

? ? private static int[] faces = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13};

?

? ? private Card[] cards;

?

? ? /**

? ? ?* 構造器

? ? ?*?

? ? ?*/

? ? public Poker() {

? ? ? ? cards = new Card[52];

? ? ? ? for(int i = 0; i < suites.length; i++) {

? ? ? ? ? ? for(int j = 0; j < faces.length; j++) {

? ? ? ? ? ? ? ? cards[i * 13 + j] = new Card(suites[i], faces[j]);

? ? ? ? ? ? }

? ? ? ? }

? ? }

?

? ? /**

? ? ?* 洗牌 (隨機亂序)

? ? ?*?

? ? ?*/

? ? public void shuffle() {

? ? ? ? for(int i = 0, len = cards.length; i < len; i++) {

? ? ? ? ? ? int index = (int) (Math.random() * len);

? ? ? ? ? ? Card temp = cards[index];

? ? ? ? ? ? cards[index] = cards[i];

? ? ? ? ? ? cards[i] = temp;

? ? ? ? }

? ? }

?

? ? /**

? ? ?* 發牌

? ? ?* @param index 發牌的位置

? ? ?*?

? ? ?*/

? ? public Card deal(int index) {

? ? ? ? return cards[index];

? ? }

?

? ? /**

? ? ?* 卡片類(一張撲克)

? ? ?* [內部類]

? ? ?* @author 駱昊

? ? ?*

? ? ?*/

? ? public class Card {

? ? ? ? private String suite;? ?// 花色

? ? ? ? private int face;? ? ? ?// 點數

?

? ? ? ? public Card(String suite, int face) {

? ? ? ? ? ? this.suite = suite;

? ? ? ? ? ? this.face = face;

? ? ? ? }

?

? ? ? ? @Override

? ? ? ? public String toString() {

? ? ? ? ? ? String faceStr = "";

? ? ? ? ? ? switch(face) {

? ? ? ? ? ? case 1: faceStr = "A"; break;

? ? ? ? ? ? case 11: faceStr = "J"; break;

? ? ? ? ? ? case 12: faceStr = "Q"; break;

? ? ? ? ? ? case 13: faceStr = "K"; break;

? ? ? ? ? ? default: faceStr = String.valueOf(face);

? ? ? ? ? ? }

? ? ? ? ? ? return suite + faceStr;

? ? ? ? }

? ? }

}?

測試代碼:?

class PokerTest {

?

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

? ? ? ? Poker poker = new Poker();

? ? ? ? poker.shuffle();? ? ? ? ? ? ? ? // 洗牌

? ? ? ? Poker.Card c1 = poker.deal(0);? // 發第一張牌

? ? ? ? // 對于非靜態內部類Card

? ? ? ? // 只有通過其外部類Poker對象才能創建Card對象

? ? ? ? Poker.Card c2 = poker.new Card("紅心", 1);? ? // 自己創建一張牌

?

? ? ? ? System.out.println(c1);? ? ?// 洗牌后的第一張

? ? ? ? System.out.println(c2);? ? ?// 打印: 紅心A

? ? }

}?

?

?面試題 - 下面的代碼哪些地方會產生編譯錯誤??

?

class Outer {

?

? ? class Inner {}

?

? ? public static void foo() { new Inner(); }

?

? ? public void bar() { new Inner(); }

?

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

? ? ? ? new Inner();

? ? }

}?

?

?注意:Java中非靜態內部類對象的創建要依賴其外部類對象,上面的面試題中foo和main方法都是靜態方法,靜態方法中沒有this,也就是說沒有所謂的外部類對象,因此無法創建內部類對象,如果要在靜態方法中創建內部類對象,可以這樣做:?

?

? ? new Outer().new Inner();?

25、Java 中會存在內存泄漏嗎,請簡單描述。? 答:理論上Java因為有垃圾回收機制(GC)不會存在內存泄露問題(這也是Java被廣泛使用于服務器端編程的一個重要原因);然而在實際開發中,可能會存在無用但可達的對象,這些對象不能被GC回收,因此也會導致內存泄露的發生。例如Hibernate的Session(一級緩存)中的對象屬于持久態,垃圾回收器是不會回收這些對象的,然而這些對象中可能存在無用的垃圾對象,如果不及時關閉(close)或清空(flush)一級緩存就可能導致內存泄露。下面例子中的代碼也會導致內存泄露。?

import java.util.Arrays;

import java.util.EmptyStackException;

?

public class MyStack<T> {

? ? private T[] elements;

? ? private int size = 0;

?

? ? private static final int INIT_CAPACITY = 16;

?

? ? public MyStack() {

? ? ? ? elements = (T[]) new Object[INIT_CAPACITY];

? ? }

?

? ? public void push(T elem) {

? ? ? ? ensureCapacity();

? ? ? ? elements[size++] = elem;

? ? }

?

? ? public T pop() {

? ? ? ? if(size == 0)?

? ? ? ? ? ? throw new EmptyStackException();

? ? ? ? return elements[--size];

? ? }

?

? ? private void ensureCapacity() {

? ? ? ? if(elements.length == size) {

? ? ? ? ? ? elements = Arrays.copyOf(elements, 2 * size + 1);

? ? ? ? }

? ? }

}?

上面的代碼實現了一個棧(先進后出(FILO))結構,乍看之下似乎沒有什么明顯的問題,它甚至可以通過你編寫的各種單元測試。然而其中的pop方法卻存在內存泄露的問題,當我們用pop方法彈出棧中的對象時,該對象不會被當作垃圾回收,即使使用棧的程序不再引用這些對象,因為棧內部維護著對這些對象的過期引用(obsolete reference)。在支持垃圾回收的語言中,內存泄露是很隱蔽的,這種內存泄露其實就是無意識的對象保持。如果一個對象引用被無意識的保留起來了,那么垃圾回收器不會處理這個對象,也不會處理該對象引用的其他對象,即使這樣的對象只有少數幾個,也可能會導致很多的對象被排除在垃圾回收之外,從而對性能造成重大影響,極端情況下會引發Disk Paging(物理內存與硬盤的虛擬內存交換數據),甚至造成OutOfMemoryError。?

26、抽象的(abstract)方法是否可同時是靜態的(static),是否可同時是本地方法(native),是否可同時被synchronized修飾?? 答:都不能。抽象方法需要子類重寫,而靜態的方法是無法被重寫的,因此二者是矛盾的。本地方法是由本地代碼(如C代碼)實現的方法,而抽象方法是沒有實現的,也是矛盾的。synchronized和方法的實現細節有關,抽象方法不涉及實現細節,因此也是相互矛盾的。?

27、闡述靜態變量和實例變量的區別。? 答:靜態變量是被static修飾符修飾的變量,也稱為類變量,它屬于類,不屬于類的任何一個對象,一個類不管創建多少個對象,靜態變量在內存中有且僅有一個拷貝;實例變量必須依存于某一實例,需要先創建對象然后通過對象才能訪問到它。靜態變量可以實現讓多個對象共享內存。?

?

?補充:在Java開發中,上下文類和工具類中通常會有大量的靜態成員。?

?

28、是否可以從一個靜態(static)方法內部發出對非靜態(non-static)方法的調用?? 答:不可以,靜態方法只能訪問靜態成員,因為非靜態方法的調用要先創建對象,在調用靜態方法時可能對象并沒有被初始化。?

29、如何實現對象克隆?? 答:有兩種方式:? ??1). 實現Cloneable接口并重寫Object類中的clone()方法;? ??2). 實現Serializable接口,通過對象的序列化和反序列化實現克隆,可以實現真正的深度克隆,代碼如下。?

import java.io.ByteArrayInputStream;

import java.io.ByteArrayOutputStream;

import java.io.ObjectInputStream;

import java.io.ObjectOutputStream;

import java.io.Serializable;

?

public class MyUtil {

?

? ? private MyUtil() {

? ? ? ? throw new AssertionError();

? ? }

?

? ? @SuppressWarnings("unchecked")

? ? public static <T extends Serializable> T clone(T obj) throws Exception {

? ? ? ? ByteArrayOutputStream bout = new ByteArrayOutputStream();

? ? ? ? ObjectOutputStream oos = new ObjectOutputStream(bout);

? ? ? ? oos.writeObject(obj);

?

? ? ? ? ByteArrayInputStream bin = new ByteArrayInputStream(bout.toByteArray());

? ? ? ? ObjectInputStream ois = new ObjectInputStream(bin);

? ? ? ? return (T) ois.readObject();

?

? ? ? ? // 說明:調用ByteArrayInputStream或ByteArrayOutputStream對象的close方法沒有任何意義

? ? ? ? // 這兩個基于內存的流只要垃圾回收器清理對象就能夠釋放資源,這一點不同于對外部資源(如文件流)的釋放

? ? }

}?

下面是測試代碼:?

import java.io.Serializable;

?

/**

?* 人類

?* @author 駱昊

?*

?*/

class Person implements Serializable {

? ? private static final long serialVersionUID = -9102017020286042305L;

?

? ? private String name;? ? // 姓名

? ? private int age;? ? ? ? // 年齡

? ? private Car car;? ? ? ? // 座駕

?

? ? public Person(String name, int age, Car car) {

? ? ? ? this.name = name;

? ? ? ? this.age = age;

? ? ? ? this.car = car;

? ? }

?

? ? public String getName() {

? ? ? ? return name;

? ? }

?

? ? public void setName(String name) {

? ? ? ? this.name = name;

? ? }

?

? ? public int getAge() {

? ? ? ? return age;

? ? }

?

? ? public void setAge(int age) {

? ? ? ? this.age = age;

? ? }

?

? ? public Car getCar() {

? ? ? ? return car;

? ? }

?

? ? public void setCar(Car car) {

? ? ? ? this.car = car;

? ? }

?

? ? @Override

? ? public String toString() {

? ? ? ? return "Person [name=" + name + ", age=" + age + ", car=" + car + "]";

? ? }

?

}?

/**

?* 小汽車類

?* @author 駱昊

?*

?*/

class Car implements Serializable {

? ? private static final long serialVersionUID = -5713945027627603702L;

?

? ? private String brand;? ? ? ?// 品牌

? ? private int maxSpeed;? ? ? ?// 最高時速

?

? ? public Car(String brand, int maxSpeed) {

? ? ? ? this.brand = brand;

? ? ? ? this.maxSpeed = maxSpeed;

? ? }

?

? ? public String getBrand() {

? ? ? ? return brand;

? ? }

?

? ? public void setBrand(String brand) {

? ? ? ? this.brand = brand;

? ? }

?

? ? public int getMaxSpeed() {

? ? ? ? return maxSpeed;

? ? }

?

? ? public void setMaxSpeed(int maxSpeed) {

? ? ? ? this.maxSpeed = maxSpeed;

? ? }

?

? ? @Override

? ? public String toString() {

? ? ? ? return "Car [brand=" + brand + ", maxSpeed=" + maxSpeed + "]";

? ? }

?

}?

class CloneTest {

?

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

? ? ? ? try {

? ? ? ? ? ? Person p1 = new Person("Hao LUO", 33, new Car("Benz", 300));

? ? ? ? ? ? Person p2 = MyUtil.clone(p1);? ?// 深度克隆

? ? ? ? ? ? p2.getCar().setBrand("BYD");

? ? ? ? ? ? // 修改克隆的Person對象p2關聯的汽車對象的品牌屬性

? ? ? ? ? ? // 原來的Person對象p1關聯的汽車不會受到任何影響

? ? ? ? ? ? // 因為在克隆Person對象時其關聯的汽車對象也被克隆了

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

? ? ? ? } catch (Exception e) {

? ? ? ? ? ? e.printStackTrace();

? ? ? ? }

? ? }

}?

?

?注意:基于序列化和反序列化實現的克隆不僅僅是深度克隆,更重要的是通過泛型限定,可以檢查出要克隆的對象是否支持序列化,這項檢查是編譯器完成的,不是在運行時拋出異常,這種是方案明顯優于使用Object類的clone方法克隆對象。讓問題在編譯的時候暴露出來總是好過把問題留到運行時。?

?

30、GC是什么?為什么要有GC?? 答:GC是垃圾收集的意思,內存處理是編程人員容易出現問題的地方,忘記或者錯誤的內存回收會導致程序或系統的不穩定甚至崩潰,Java提供的GC功能可以自動監測對象是否超過作用域從而達到自動回收內存的目的,Java語言沒有提供釋放已分配內存的顯示操作方法。Java程序員不用擔心內存管理,因為垃圾收集器會自動進行管理。要請求垃圾收集,可以調用下面的方法之一:System.gc() 或Runtime.getRuntime().gc() ,但JVM可以屏蔽掉顯示的垃圾回收調用。? 垃圾回收可以有效的防止內存泄露,有效的使用可以使用的內存。垃圾回收器通常是作為一個單獨的低優先級的線程運行,不可預知的情況下對內存堆中已經死亡的或者長時間沒有使用的對象進行清除和回收,程序員不能實時的調用垃圾回收器對某個對象或所有對象進行垃圾回收。在Java誕生初期,垃圾回收是Java最大的亮點之一,因為服務器端的編程需要有效的防止內存泄露問題,然而時過境遷,如今Java的垃圾回收機制已經成為被詬病的東西。移動智能終端用戶通常覺得iOS的系統比Android系統有更好的用戶體驗,其中一個深層次的原因就在于Android系統中垃圾回收的不可預知性。?

?

?補充:垃圾回收機制有很多種,包括:分代復制垃圾回收、標記垃圾回收、增量垃圾回收等方式。標準的Java進程既有棧又有堆。棧保存了原始型局部變量,堆保存了要創建的對象。Java平臺對堆內存回收和再利用的基本算法被稱為標記和清除,但是Java對其進行了改進,采用“分代式垃圾收集”。這種方法會跟Java對象的生命周期將堆內存劃分為不同的區域,在垃圾收集過程中,可能會將對象移動到不同區域:? - 伊甸園(Eden):這是對象最初誕生的區域,并且對大多數對象來說,這里是它們唯一存在過的區域。? - 幸存者樂園(Survivor):從伊甸園幸存下來的對象會被挪到這里。? - 終身頤養園(Tenured):這是足夠老的幸存對象的歸宿。年輕代收集(Minor-GC)過程是不會觸及這個地方的。當年輕代收集不能把對象放進終身頤養園時,就會觸發一次完全收集(Major-GC),這里可能還會牽扯到壓縮,以便為大對象騰出足夠的空間。?

?

與垃圾回收相關的JVM參數:?

?

?-Xms / -Xmx — 堆的初始大小 / 堆的最大大小-Xmn — 堆中年輕代的大小-XX:-DisableExplicitGC — 讓System.gc()不產生任何作用-XX:+PrintGCDetails — 打印GC的細節-XX:+PrintGCDateStamps — 打印GC操作的時間戳-XX:NewSize / XX:MaxNewSize — 設置新生代大小/新生代最大大小-XX:NewRatio — 可以設置老生代和新生代的比例-XX:PrintTenuringDistribution — 設置每次新生代GC后輸出幸存者樂園中對象年齡的分布-XX:InitialTenuringThreshold / -XX:MaxTenuringThreshold:設置老年代閥值的初始值和最大值-XX:TargetSurvivorRatio:設置幸存區的目標使用率?

?

31、String s = new String("xyz");創建了幾個字符串對象?? 答:兩個對象,一個是靜態區的"xyz",一個是用new創建在堆上的對象。?

32、接口是否可繼承(extends)接口?抽象類是否可實現(implements)接口?抽象類是否可繼承具體類(concrete class)?? 答:接口可以繼承接口,而且支持多重繼承。抽象類可以實現(implements)接口,抽象類可繼承具體類也可以繼承抽象類。?

33、一個".java"源文件中是否可以包含多個類(不是內部類)?有什么限制?? 答:可以,但一個源文件中最多只能有一個公開類(public class)而且文件名必須和公開類的類名完全保持一致。?

34、Anonymous Inner Class(匿名內部類)是否可以繼承其它類?是否可以實現接口?? 答:可以繼承其他類或實現其他接口,在Swing編程和Android開發中常用此方式來實現事件監聽和回調。?

35、內部類可以引用它的包含類(外部類)的成員嗎?有沒有什么限制?? 答:一個內部類對象可以訪問創建它的外部類對象的成員,包括私有成員。?

36、Java 中的final關鍵字有哪些用法?? 答:(1)修飾類:表示該類不能被繼承;(2)修飾方法:表示方法不能被重寫;(3)修飾變量:表示變量只能一次賦值以后值不能被修改(常量)。?

37、指出下面程序的運行結果。?

class A {

?

? ? static {

? ? ? ? System.out.print("1");

? ? }

?

? ? public A() {

? ? ? ? System.out.print("2");

? ? }

}

?

class B extends A{

?

? ? static {

? ? ? ? System.out.print("a");

? ? }

?

? ? public B() {

? ? ? ? System.out.print("b");

? ? }

}

?

public class Hello {

?

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

? ? ? ? A ab = new B();

? ? ? ? ab = new B();

? ? }

?

}?

答:執行結果:1a2b2b。創建對象時構造器的調用順序是:先初始化靜態成員,然后調用父類構造器,再初始化非靜態成員,最后調用自身構造器。?

?

?提示:如果不能給出此題的正確答案,說明之前第21題Java類加載機制還沒有完全理解,趕緊再看看吧。?

?

38、數據類型之間的轉換:? - 如何將字符串轉換為基本數據類型?? - 如何將基本數據類型轉換為字符串?? 答:? - 調用基本數據類型對應的包裝類中的方法parseXXX(String)或valueOf(String)即可返回相應基本類型;? - 一種方法是將基本數據類型與空字符串("")連接(+)即可獲得其所對應的字符串;另一種方法是調用String 類中的valueOf()方法返回相應字符串?

39、如何實現字符串的反轉及替換?? 答:方法很多,可以自己寫實現也可以使用String或StringBuffer/StringBuilder中的方法。有一道很常見的面試題是用遞歸實現字符串反轉,代碼如下所示:?

? ? public static String reverse(String originStr) {

? ? ? ? if(originStr == null || originStr.length() <= 1)?

? ? ? ? ? ? return originStr;

? ? ? ? return reverse(originStr.substring(1)) + originStr.charAt(0);

? ? }?

40、怎樣將GB2312編碼的字符串轉換為ISO-8859-1編碼的字符串?? 答:代碼如下所示:?

String s1 = "你好";

String s2 = new String(s1.getBytes("GB2312"), "ISO-8859-1");?

41、日期和時間:? - 如何取得年月日、小時分鐘秒?? - 如何取得從1970年1月1日0時0分0秒到現在的毫秒數?? - 如何取得某月的最后一天?? - 如何格式化日期?? 答:? 問題1:創建java.util.Calendar 實例,調用其get()方法傳入不同的參數即可獲得參數所對應的值。Java 8中可以使用java.time.LocalDateTimel來獲取,代碼如下所示。?

public class DateTimeTest {

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

? ? ? ? Calendar cal = Calendar.getInstance();

? ? ? ? System.out.println(cal.get(Calendar.YEAR));

? ? ? ? System.out.println(cal.get(Calendar.MONTH));? ? // 0 - 11

? ? ? ? System.out.println(cal.get(Calendar.DATE));

? ? ? ? System.out.println(cal.get(Calendar.HOUR_OF_DAY));

? ? ? ? System.out.println(cal.get(Calendar.MINUTE));

? ? ? ? System.out.println(cal.get(Calendar.SECOND));

?

? ? ? ? // Java 8

? ? ? ? LocalDateTime dt = LocalDateTime.now();

? ? ? ? System.out.println(dt.getYear());

? ? ? ? System.out.println(dt.getMonthValue());? ? ?// 1 - 12

? ? ? ? System.out.println(dt.getDayOfMonth());

? ? ? ? System.out.println(dt.getHour());

? ? ? ? System.out.println(dt.getMinute());

? ? ? ? System.out.println(dt.getSecond());

? ? }

}?

問題2:以下方法均可獲得該毫秒數。?

Calendar.getInstance().getTimeInMillis();

System.currentTimeMillis();

Clock.systemDefaultZone().millis(); // Java 8?

問題3:代碼如下所示。?

Calendar time = Calendar.getInstance();

time.getActualMaximum(Calendar.DAY_OF_MONTH);?

問題4:利用java.text.DataFormat 的子類(如SimpleDateFormat類)中的format(Date)方法可將日期格式化。Java 8中可以用java.time.format.DateTimeFormatter來格式化時間日期,代碼如下所示。?

import java.text.SimpleDateFormat;

import java.time.LocalDate;

import java.time.format.DateTimeFormatter;

import java.util.Date;

?

class DateFormatTest {

?

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

? ? ? ? SimpleDateFormat oldFormatter = new SimpleDateFormat("yyyy/MM/dd");

? ? ? ? Date date1 = new Date();

? ? ? ? System.out.println(oldFormatter.format(date1));

?

? ? ? ? // Java 8

? ? ? ? DateTimeFormatter newFormatter = DateTimeFormatter.ofPattern("yyyy/MM/dd");

? ? ? ? LocalDate date2 = LocalDate.now();

? ? ? ? System.out.println(date2.format(newFormatter));

? ? }

}?

?

?補充:Java的時間日期API一直以來都是被詬病的東西,為了解決這一問題,Java 8中引入了新的時間日期API,其中包括LocalDate、LocalTime、LocalDateTime、Clock、Instant等類,這些的類的設計都使用了不變模式,因此是線程安全的設計。如果不理解這些內容,可以參考我的另一篇文章《關于Java并發編程的總結和思考》。?

?

42、打印昨天的當前時刻。? 答:?

import java.util.Calendar;

?

class YesterdayCurrent {

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

? ? ? ? Calendar cal = Calendar.getInstance();

? ? ? ? cal.add(Calendar.DATE, -1);

? ? ? ? System.out.println(cal.getTime());

? ? }

}?

在Java 8中,可以用下面的代碼實現相同的功能。?

import java.time.LocalDateTime;

?

class YesterdayCurrent {

?

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

? ? ? ? LocalDateTime today = LocalDateTime.now();

? ? ? ? LocalDateTime yesterday = today.minusDays(1);

?

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

? ? }

}?

43、比較一下Java和JavaSciprt。? 答:JavaScript 與Java是兩個公司開發的不同的兩個產品。Java 是原Sun Microsystems公司推出的面向對象的程序設計語言,特別適合于互聯網應用程序開發;而JavaScript是Netscape公司的產品,為了擴展Netscape瀏覽器的功能而開發的一種可以嵌入Web頁面中運行的基于對象和事件驅動的解釋性語言。JavaScript的前身是LiveScript;而Java的前身是Oak語言。? 下面對兩種語言間的異同作如下比較:? - 基于對象和面向對象:Java是一種真正的面向對象的語言,即使是開發簡單的程序,必須設計對象;JavaScript是種腳本語言,它可以用來制作與網絡無關的,與用戶交互作用的復雜軟件。它是一種基于對象(Object-Based)和事件驅動(Event-Driven)的編程語言,因而它本身提供了非常豐富的內部對象供設計人員使用。? - 解釋和編譯:Java的源代碼在執行之前,必須經過編譯。JavaScript是一種解釋性編程語言,其源代碼不需經過編譯,由瀏覽器解釋執行。(目前的瀏覽器幾乎都使用了JIT(即時編譯)技術來提升JavaScript的運行效率)? - 強類型變量和類型弱變量:Java采用強類型變量檢查,即所有變量在編譯之前必須作聲明;JavaScript中變量是弱類型的,甚至在使用變量前可以不作聲明,JavaScript的解釋器在運行時檢查推斷其數據類型。? - 代碼格式不一樣。?

?

?補充:上面列出的四點是網上流傳的所謂的標準答案。其實Java和JavaScript最重要的區別是一個是靜態語言,一個是動態語言。目前的編程語言的發展趨勢是函數式語言和動態語言。在Java中類(class)是一等公民,而JavaScript中函數(function)是一等公民,因此JavaScript支持函數式編程,可以使用Lambda函數和閉包(closure),當然Java 8也開始支持函數式編程,提供了對Lambda表達式以及函數式接口的支持。對于這類問題,在面試的時候最好還是用自己的語言回答會更加靠譜,不要背網上所謂的標準答案。?

?

44、什么時候用斷言(assert)?? 答:斷言在軟件開發中是一種常用的調試方式,很多開發語言中都支持這種機制。一般來說,斷言用于保證程序最基本、關鍵的正確性。斷言檢查通常在開發和測試時開啟。為了保證程序的執行效率,在軟件發布后斷言檢查通常是關閉的。斷言是一個包含布爾表達式的語句,在執行這個語句時假定該表達式為true;如果表達式的值為false,那么系統會報告一個AssertionError。斷言的使用如下面的代碼所示:?

assert(a > 0); // throws an AssertionError if a <= 0?

斷言可以有兩種形式:? assert Expression1;? assert Expression1 : Expression2 ;? Expression1 應該總是產生一個布爾值。? Expression2 可以是得出一個值的任意表達式;這個值用于生成顯示更多調試信息的字符串消息。?

要在運行時啟用斷言,可以在啟動JVM時使用-enableassertions或者-ea標記。要在運行時選擇禁用斷言,可以在啟動JVM時使用-da或者-disableassertions標記。要在系統類中啟用或禁用斷言,可使用-esa或-dsa標記。還可以在包的基礎上啟用或者禁用斷言。?

?

?注意:斷言不應該以任何方式改變程序的狀態。簡單的說,如果希望在不滿足某些條件時阻止代碼的執行,就可以考慮用斷言來阻止它。?

?

45、Error和Exception有什么區別?? 答:Error表示系統級的錯誤和程序不必處理的異常,是恢復不是不可能但很困難的情況下的一種嚴重問題;比如內存溢出,不可能指望程序能處理這樣的情況;Exception表示需要捕捉或者需要程序進行處理的異常,是一種設計或實現問題;也就是說,它表示如果程序運行正常,從不會發生的情況。?

?

?面試題:2005年摩托羅拉的面試中曾經問過這么一個問題“If a process reports a stack overflow run-time error, what’s the most possible cause?”,給了四個選項a. lack of memory; b. write on an invalid memory space; c. recursive function calling; d. array index out of boundary. Java程序在運行時也可能會遭遇StackOverflowError,這是一個無法恢復的錯誤,只能重新修改代碼了,這個面試題的答案是c。如果寫了不能迅速收斂的遞歸,則很有可能引發棧溢出的錯誤,如下所示:?

?

class StackOverflowErrorTest {

?

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

? ? ? ? main(null);

? ? }

}?

?

?提示:用遞歸編寫程序時一定要牢記兩點:1. 遞歸公式;2. 收斂條件(什么時候就不再繼續遞歸)。?

?

46、try{}里有一個return語句,那么緊跟在這個try后的finally{}里的代碼會不會被執行,什么時候被執行,在return前還是后?? 答:會執行,在方法返回調用者前執行。?

?

?注意:在finally中改變返回值的做法是不好的,因為如果存在finally代碼塊,try中的return語句不會立馬返回調用者,而是記錄下返回值待finally代碼塊執行完畢之后再向調用者返回其值,然后如果在finally中修改了返回值,就會返回修改后的值。顯然,在finally中返回或者修改返回值會對程序造成很大的困擾,C#中直接用編譯錯誤的方式來阻止程序員干這種齷齪的事情,Java中也可以通過提升編譯器的語法檢查級別來產生警告或錯誤,Eclipse中可以在如圖所示的地方進行設置,強烈建議將此項設置為編譯錯誤。?

?

?

47、Java語言如何進行異常處理,關鍵字:throws、throw、try、catch、finally分別如何使用?? 答:Java通過面向對象的方法進行異常處理,把各種不同的異常進行分類,并提供了良好的接口。在Java中,每個異常都是一個對象,它是Throwable類或其子類的實例。當一個方法出現異常后便拋出一個異常對象,該對象中包含有異常信息,調用這個對象的方法可以捕獲到這個異常并可以對其進行處理。Java的異常處理是通過5個關鍵詞來實現的:try、catch、throw、throws和finally。一般情況下是用try來執行一段程序,如果系統會拋出(throw)一個異常對象,可以通過它的類型來捕獲(catch)它,或通過總是執行代碼塊(finally)來處理;try用來指定一塊預防所有異常的程序;catch子句緊跟在try塊后面,用來指定你想要捕獲的異常的類型;throw語句用來明確地拋出一個異常;throws用來聲明一個方法可能拋出的各種異常(當然聲明異常時允許無病呻吟);finally為確保一段代碼不管發生什么異常狀況都要被執行;try語句可以嵌套,每當遇到一個try語句,異常的結構就會被放入異常棧中,直到所有的try語句都完成。如果下一級的try語句沒有對某種異常進行處理,異常棧就會執行出棧操作,直到遇到有處理這種異常的try語句或者最終將異常拋給JVM。?

48、運行時異常與受檢異常有何異同?? 答:異常表示程序運行過程中可能出現的非正常狀態,運行時異常表示虛擬機的通常操作中可能遇到的異常,是一種常見運行錯誤,只要程序設計得沒有問題通常就不會發生。受檢異常跟程序運行的上下文環境有關,即使程序設計無誤,仍然可能因使用的問題而引發。Java編譯器要求方法必須聲明拋出可能發生的受檢異常,但是并不要求必須聲明拋出未被捕獲的運行時異常。異常和繼承一樣,是面向對象程序設計中經常被濫用的東西,在Effective Java中對異常的使用給出了以下指導原則:? - 不要將異常處理用于正常的控制流(設計良好的API不應該強迫它的調用者為了正常的控制流而使用異常)? - 對可以恢復的情況使用受檢異常,對編程錯誤使用運行時異常? - 避免不必要的使用受檢異常(可以通過一些狀態檢測手段來避免異常的發生)? - 優先使用標準的異常? - 每個方法拋出的異常都要有文檔? - 保持異常的原子性? - 不要在catch中忽略掉捕獲到的異常?

49、列出一些你常見的運行時異常?? 答:? - ArithmeticException(算術異常)? - ClassCastException (類轉換異常)? - IllegalArgumentException (非法參數異常)? - IndexOutOfBoundsException (下標越界異常)? - NullPointerException (空指針異常)? - SecurityException (安全異常)?

50、闡述final、finally、finalize的區別。? 答:? - final:修飾符(關鍵字)有三種用法:如果一個類被聲明為final,意味著它不能再派生出新的子類,即不能被繼承,因此它和abstract是反義詞。將變量聲明為final,可以保證它們在使用中不被改變,被聲明為final的變量必須在聲明時給定初值,而在以后的引用中只能讀取不可修改。被聲明為final的方法也同樣只能使用,不能在子類中被重寫。? - finally:通常放在try…catch…的后面構造總是執行代碼塊,這就意味著程序無論正常執行還是發生異常,這里的代碼只要JVM不關閉都能執行,可以將釋放外部資源的代碼寫在finally塊中。? - finalize:Object類中定義的方法,Java中允許使用finalize()方法在垃圾收集器將對象從內存中清除出去之前做必要的清理工作。這個方法是由垃圾收集器在銷毀對象時調用的,通過重寫finalize()方法可以整理系統資源或者執行其他清理工作。?

51、類ExampleA繼承Exception,類ExampleB繼承ExampleA。? 有如下代碼片斷:?

try {

? ? throw new ExampleB("b")

} catch(ExampleA e){

? ? System.out.println("ExampleA");

} catch(Exception e){

? ? System.out.println("Exception");

}?

請問執行此段代碼的輸出是什么?? 答:輸出:ExampleA。(根據里氏代換原則[能使用父類型的地方一定能使用子類型],抓取ExampleA類型異常的catch塊能夠抓住try塊中拋出的ExampleB類型的異常)?

?

?面試題 - 說出下面代碼的運行結果。(此題的出處是《Java編程思想》一書)?

?

class Annoyance extends Exception {}

class Sneeze extends Annoyance {}

?

class Human {

?

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

? ? ? ? throws Exception {

? ? ? ? try {

? ? ? ? ? ? try {

? ? ? ? ? ? ? ? throw new Sneeze();

? ? ? ? ? ? }?

? ? ? ? ? ? catch ( Annoyance a ) {

? ? ? ? ? ? ? ? System.out.println("Caught Annoyance");

? ? ? ? ? ? ? ? throw a;

? ? ? ? ? ? }

? ? ? ? }?

? ? ? ? catch ( Sneeze s ) {

? ? ? ? ? ? System.out.println("Caught Sneeze");

? ? ? ? ? ? return ;

? ? ? ? }

? ? ? ? finally {

? ? ? ? ? ? System.out.println("Hello World!");

? ? ? ? }

? ? }

}?

52、List、Set、Map是否繼承自Collection接口?? 答:List、Set 是,Map 不是。Map是鍵值對映射容器,與List和Set有明顯的區別,而Set存儲的零散的元素且不允許有重復元素(數學中的集合也是如此),List是線性結構的容器,適用于按數值索引訪問元素的情形。?

53、闡述ArrayList、Vector、LinkedList的存儲性能和特性。? 答:ArrayList 和Vector都是使用數組方式存儲數據,此數組元素數大于實際存儲的數據以便增加和插入元素,它們都允許直接按序號索引元素,但是插入元素要涉及數組元素移動等內存操作,所以索引數據快而插入數據慢,Vector中的方法由于添加了synchronized修飾,因此Vector是線程安全的容器,但性能上較ArrayList差,因此已經是Java中的遺留容器。LinkedList使用雙向鏈表實現存儲(將內存中零散的內存單元通過附加的引用關聯起來,形成一個可以按序號索引的線性結構,這種鏈式存儲方式與數組的連續存儲方式相比,內存的利用率更高),按序號索引數據需要進行前向或后向遍歷,但是插入數據時只需要記錄本項的前后項即可,所以插入速度較快。Vector屬于遺留容器(Java早期的版本中提供的容器,除此之外,Hashtable、Dictionary、BitSet、Stack、Properties都是遺留容器),已經不推薦使用,但是由于ArrayList和LinkedListed都是非線程安全的,如果遇到多個線程操作同一個容器的場景,則可以通過工具類Collections中的synchronizedList方法將其轉換成線程安全的容器后再使用(這是對裝潢模式的應用,將已有對象傳入另一個類的構造器中創建新的對象來增強實現)。?

?

?補充:遺留容器中的Properties類和Stack類在設計上有嚴重的問題,Properties是一個鍵和值都是字符串的特殊的鍵值對映射,在設計上應該是關聯一個Hashtable并將其兩個泛型參數設置為String類型,但是Java API中的Properties直接繼承了Hashtable,這很明顯是對繼承的濫用。這里復用代碼的方式應該是Has-A關系而不是Is-A關系,另一方面容器都屬于工具類,繼承工具類本身就是一個錯誤的做法,使用工具類最好的方式是Has-A關系(關聯)或Use-A關系(依賴)。同理,Stack類繼承Vector也是不正確的。Sun公司的工程師們也會犯這種低級錯誤,讓人唏噓不已。?

?

54、Collection和Collections的區別?? 答:Collection是一個接口,它是Set、List等容器的父接口;Collections是個一個工具類,提供了一系列的靜態方法來輔助容器操作,這些方法包括對容器的搜索、排序、線程安全化等等。?

55、List、Map、Set三個接口存取元素時,各有什么特點?? 答:List以特定索引來存取元素,可以有重復元素。Set不能存放重復元素(用對象的equals()方法來區分元素是否重復)。Map保存鍵值對(key-value pair)映射,映射關系可以是一對一或多對一。Set和Map容器都有基于哈希存儲和排序樹的兩種實現版本,基于哈希存儲的版本理論存取時間復雜度為O(1),而基于排序樹版本的實現在插入或刪除元素時會按照元素或元素的鍵(key)構成排序樹從而達到排序和去重的效果。?

56、TreeMap和TreeSet在排序時如何比較元素?Collections工具類中的sort()方法如何比較元素?? 答:TreeSet要求存放的對象所屬的類必須實現Comparable接口,該接口提供了比較元素的compareTo()方法,當插入元素時會回調該方法比較元素的大小。TreeMap要求存放的鍵值對映射的鍵必須實現Comparable接口從而根據鍵對元素進行排序。Collections工具類的sort方法有兩種重載的形式,第一種要求傳入的待排序容器中存放的對象比較實現Comparable接口以實現元素的比較;第二種不強制性的要求容器中的元素必須可比較,但是要求傳入第二個參數,參數是Comparator接口的子類型(需要重寫compare方法實現元素的比較),相當于一個臨時定義的排序規則,其實就是通過接口注入比較元素大小的算法,也是對回調模式的應用(Java中對函數式編程的支持)。? 例子1:?

?

public class Student implements Comparable<Student> {

? ? private String name;? ? ? ? // 姓名

? ? private int age;? ? ? ? ? ? // 年齡

?

? ? public Student(String name, int age) {

? ? ? ? this.name = name;

? ? ? ? this.age = age;

? ? }

?

? ? @Override

? ? public String toString() {

? ? ? ? return "Student [name=" + name + ", age=" + age + "]";

? ? }

?

? ? @Override

? ? public int compareTo(Student o) {

? ? ? ? return this.age - o.age; // 比較年齡(年齡的升序)

? ? }

?

}?

import java.util.Set;

import java.util.TreeSet;

?

class Test01 {

?

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

? ? ? ? Set<Student> set = new TreeSet<>();? ? ?// Java 7的鉆石語法(構造器后面的尖括號中不需要寫類型)

? ? ? ? set.add(new Student("Hao LUO", 33));

? ? ? ? set.add(new Student("XJ WANG", 32));

? ? ? ? set.add(new Student("Bruce LEE", 60));

? ? ? ? set.add(new Student("Bob YANG", 22));

?

? ? ? ? for(Student stu : set) {

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

? ? ? ? }

//? ? ? 輸出結果:?

//? ? ? Student [name=Bob YANG, age=22]

//? ? ? Student [name=XJ WANG, age=32]

//? ? ? Student [name=Hao LUO, age=33]

//? ? ? Student [name=Bruce LEE, age=60]

? ? }

}?

例子2:?

public class Student {

? ? private String name;? ? // 姓名

? ? private int age;? ? ? ? // 年齡

?

? ? public Student(String name, int age) {

? ? ? ? this.name = name;

? ? ? ? this.age = age;

? ? }

?

? ? /**

? ? ?* 獲取學生姓名

? ? ?*/

? ? public String getName() {

? ? ? ? return name;

? ? }

?

? ? /**

? ? ?* 獲取學生年齡

? ? ?*/

? ? public int getAge() {

? ? ? ? return age;

? ? }

?

? ? @Override

? ? public String toString() {

? ? ? ? return "Student [name=" + name + ", age=" + age + "]";

? ? }

?

}?

import java.util.ArrayList;

import java.util.Collections;

import java.util.Comparator;

import java.util.List;

?

class Test02 {

?

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

? ? ? ? List<Student> list = new ArrayList<>();? ? ?// Java 7的鉆石語法(構造器后面的尖括號中不需要寫類型)

? ? ? ? list.add(new Student("Hao LUO", 33));

? ? ? ? list.add(new Student("XJ WANG", 32));

? ? ? ? list.add(new Student("Bruce LEE", 60));

? ? ? ? list.add(new Student("Bob YANG", 22));

?

? ? ? ? // 通過sort方法的第二個參數傳入一個Comparator接口對象

? ? ? ? // 相當于是傳入一個比較對象大小的算法到sort方法中

? ? ? ? // 由于Java中沒有函數指針、仿函數、委托這樣的概念

? ? ? ? // 因此要將一個算法傳入一個方法中唯一的選擇就是通過接口回調

? ? ? ? Collections.sort(list, new Comparator<Student> () {

?

? ? ? ? ? ? @Override

? ? ? ? ? ? public int compare(Student o1, Student o2) {

? ? ? ? ? ? ? ? return o1.getName().compareTo(o2.getName());? ? // 比較學生姓名

? ? ? ? ? ? }

? ? ? ? });

?

? ? ? ? for(Student stu : list) {

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

? ? ? ? }

//? ? ? 輸出結果:?

//? ? ? Student [name=Bob YANG, age=22]

//? ? ? Student [name=Bruce LEE, age=60]

//? ? ? Student [name=Hao LUO, age=33]

//? ? ? Student [name=XJ WANG, age=32]

? ? }

}?

57、Thread類的sleep()方法和對象的wait()方法都可以讓線程暫停執行,它們有什么區別?? 答:sleep()方法(休眠)是線程類(Thread)的靜態方法,調用此方法會讓當前線程暫停執行指定的時間,將執行機會(CPU)讓給其他線程,但是對象的鎖依然保持,因此休眠時間結束后會自動恢復(線程回到就緒狀態,請參考第66題中的線程狀態轉換圖)。wait()是Object類的方法,調用對象的wait()方法導致當前線程放棄對象的鎖(線程暫停執行),進入對象的等待池(wait pool),只有調用對象的notify()方法(或notifyAll()方法)時才能喚醒等待池中的線程進入等鎖池(lock pool),如果線程重新獲得對象的鎖就可以進入就緒狀態。?

?

?補充:可能不少人對什么是進程,什么是線程還比較模糊,對于為什么需要多線程編程也不是特別理解。簡單的說:進程是具有一定獨立功能的程序關于某個數據集合上的一次運行活動,是操作系統進行資源分配和調度的一個獨立單位;線程是進程的一個實體,是CPU調度和分派的基本單位,是比進程更小的能獨立運行的基本單位。線程的劃分尺度小于進程,這使得多線程程序的并發性高;進程在執行時通常擁有獨立的內存單元,而線程之間可以共享內存。使用多線程的編程通常能夠帶來更好的性能和用戶體驗,但是多線程的程序對于其他程序是不友好的,因為它可能占用了更多的CPU資源。當然,也不是線程越多,程序的性能就越好,因為線程之間的調度和切換也會浪費CPU時間。時下很時髦的Node.js就采用了單線程異步I/O的工作模式。?

?

58、線程的sleep()方法和yield()方法有什么區別?? 答:? ① sleep()方法給其他線程運行機會時不考慮線程的優先級,因此會給低優先級的線程以運行的機會;yield()方法只會給相同優先級或更高優先級的線程以運行的機會;? ② 線程執行sleep()方法后轉入阻塞(blocked)狀態,而執行yield()方法后轉入就緒(ready)狀態;? ③ sleep()方法聲明拋出InterruptedException,而yield()方法沒有聲明任何異常;? ④ sleep()方法比yield()方法(跟操作系統CPU調度相關)具有更好的可移植性。?

59、當一個線程進入一個對象的synchronized方法A之后,其它線程是否可進入此對象的synchronized方法B?? 答:不能。其它線程只能訪問該對象的非同步方法,同步方法則不能進入。因為非靜態方法上的synchronized修飾符要求執行方法時要獲得對象的鎖,如果已經進入A方法說明對象鎖已經被取走,那么試圖進入B方法的線程就只能在等鎖池(注意不是等待池哦)中等待對象的鎖。?

60、請說出與線程同步以及線程調度相關的方法。? 答:? - wait():使一個線程處于等待(阻塞)狀態,并且釋放所持有的對象的鎖;? - sleep():使一個正在運行的線程處于睡眠狀態,是一個靜態方法,調用此方法要處理InterruptedException異常;? - notify():喚醒一個處于等待狀態的線程,當然在調用此方法的時候,并不能確切的喚醒某一個等待狀態的線程,而是由JVM確定喚醒哪個線程,而且與優先級無關;? - notityAll():喚醒所有處于等待狀態的線程,該方法并不是將對象的鎖給所有線程,而是讓它們競爭,只有獲得鎖的線程才能進入就緒狀態;?

?

?提示:關于Java多線程和并發編程的問題,建議大家看我的另一篇文章《關于Java并發編程的總結和思考》。?

?補充:Java 5通過Lock接口提供了顯式的鎖機制(explicit lock),增強了靈活性以及對線程的協調。Lock接口中定義了加鎖(lock())和解鎖(unlock())的方法,同時還提供了newCondition()方法來產生用于線程之間通信的Condition對象;此外,Java 5還提供了信號量機制(semaphore),信號量可以用來限制對某個共享資源進行訪問的線程的數量。在對資源進行訪問之前,線程必須得到信號量的許可(調用Semaphore對象的acquire()方法);在完成對資源的訪問后,線程必須向信號量歸還許可(調用Semaphore對象的release()方法)。?

?

下面的例子演示了100個線程同時向一個銀行賬戶中存入1元錢,在沒有使用同步機制和使用同步機制情況下的執行情況。?

銀行賬戶類:?

/**

?* 銀行賬戶

?* @author 駱昊

?*

?*/

public class Account {

? ? private double balance;? ? ?// 賬戶余額

?

? ? /**

? ? ?* 存款

? ? ?* @param money 存入金額

? ? ?*/

? ? public void deposit(double money) {

? ? ? ? double newBalance = balance + money;

? ? ? ? try {

? ? ? ? ? ? Thread.sleep(10);? ?// 模擬此業務需要一段處理時間

? ? ? ? }

? ? ? ? catch(InterruptedException ex) {

? ? ? ? ? ? ex.printStackTrace();

? ? ? ? }

? ? ? ? balance = newBalance;

? ? }

?

? ? /**

? ? ?* 獲得賬戶余額

? ? ?*/

? ? public double getBalance() {

? ? ? ? return balance;

? ? }

}?

存錢線程類:?

/**

?* 存錢線程

?* @author 駱昊

?*

?*/

public class AddMoneyThread implements Runnable {

? ? private Account account;? ? // 存入賬戶

? ? private double money;? ? ? ?// 存入金額

?

? ? public AddMoneyThread(Account account, double money) {

? ? ? ? this.account = account;

? ? ? ? this.money = money;

? ? }

?

? ? @Override

? ? public void run() {

? ? ? ? account.deposit(money);

? ? }

?

}?

測試類:?

import java.util.concurrent.ExecutorService;

import java.util.concurrent.Executors;

?

public class Test01 {

?

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

? ? ? ? Account account = new Account();

? ? ? ? ExecutorService service = Executors.newFixedThreadPool(100);

?

? ? ? ? for(int i = 1; i <= 100; i++) {

? ? ? ? ? ? service.execute(new AddMoneyThread(account, 1));

? ? ? ? }

?

? ? ? ? service.shutdown();

?

? ? ? ? while(!service.isTerminated()) {}

?

? ? ? ? System.out.println("賬戶余額: " + account.getBalance());

? ? }

}?

在沒有同步的情況下,執行結果通常是顯示賬戶余額在10元以下,出現這種狀況的原因是,當一個線程A試圖存入1元的時候,另外一個線程B也能夠進入存款的方法中,線程B讀取到的賬戶余額仍然是線程A存入1元錢之前的賬戶余額,因此也是在原來的余額0上面做了加1元的操作,同理線程C也會做類似的事情,所以最后100個線程執行結束時,本來期望賬戶余額為100元,但實際得到的通常在10元以下(很可能是1元哦)。解決這個問題的辦法就是同步,當一個線程對銀行賬戶存錢時,需要將此賬戶鎖定,待其操作完成后才允許其他的線程進行操作,代碼有如下幾種調整方案:?

在銀行賬戶的存款(deposit)方法上同步(synchronized)關鍵字?

/**

?* 銀行賬戶

?* @author 駱昊

?*

?*/

public class Account {

? ? private double balance;? ? ?// 賬戶余額

?

? ? /**

? ? ?* 存款

? ? ?* @param money 存入金額

? ? ?*/

? ? public synchronized void deposit(double money) {

? ? ? ? double newBalance = balance + money;

? ? ? ? try {

? ? ? ? ? ? Thread.sleep(10);? ?// 模擬此業務需要一段處理時間

? ? ? ? }

? ? ? ? catch(InterruptedException ex) {

? ? ? ? ? ? ex.printStackTrace();

? ? ? ? }

? ? ? ? balance = newBalance;

? ? }

?

? ? /**

? ? ?* 獲得賬戶余額

? ? ?*/

? ? public double getBalance() {

? ? ? ? return balance;

? ? }

}?

在線程調用存款方法時對銀行賬戶進行同步?

/**

?* 存錢線程

?* @author 駱昊

?*

?*/

public class AddMoneyThread implements Runnable {

? ? private Account account;? ? // 存入賬戶

? ? private double money;? ? ? ?// 存入金額

?

? ? public AddMoneyThread(Account account, double money) {

? ? ? ? this.account = account;

? ? ? ? this.money = money;

? ? }

?

? ? @Override

? ? public void run() {

? ? ? ? synchronized (account) {

? ? ? ? ? ? account.deposit(money);?

? ? ? ? }

? ? }

?

}?

通過Java 5顯示的鎖機制,為每個銀行賬戶創建一個鎖對象,在存款操作進行加鎖和解鎖的操作?

import java.util.concurrent.locks.Lock;

import java.util.concurrent.locks.ReentrantLock;

?

/**

?* 銀行賬戶

?*?

?* @author 駱昊

?*

?*/

public class Account {

? ? private Lock accountLock = new ReentrantLock();

? ? private double balance; // 賬戶余額

?

? ? /**

? ? ?* 存款

? ? ?*?

? ? ?* @param money

? ? ?*? ? ? ? ? ? 存入金額

? ? ?*/

? ? public void deposit(double money) {

? ? ? ? accountLock.lock();

? ? ? ? try {

? ? ? ? ? ? double newBalance = balance + money;

? ? ? ? ? ? try {

? ? ? ? ? ? ? ? Thread.sleep(10); // 模擬此業務需要一段處理時間

? ? ? ? ? ? }

? ? ? ? ? ? catch (InterruptedException ex) {

? ? ? ? ? ? ? ? ex.printStackTrace();

? ? ? ? ? ? }

? ? ? ? ? ? balance = newBalance;

? ? ? ? }

? ? ? ? finally {

? ? ? ? ? ? accountLock.unlock();

? ? ? ? }

? ? }

?

? ? /**

? ? ?* 獲得賬戶余額

? ? ?*/

? ? public double getBalance() {

? ? ? ? return balance;

? ? }

}?

按照上述三種方式對代碼進行修改后,重寫執行測試代碼Test01,將看到最終的賬戶余額為100元。當然也可以使用Semaphore或CountdownLatch來實現同步。?

61、編寫多線程程序有幾種實現方式?? 答:Java 5以前實現多線程有兩種實現方法:一種是繼承Thread類;另一種是實現Runnable接口。兩種方式都要通過重寫run()方法來定義線程的行為,推薦使用后者,因為Java中的繼承是單繼承,一個類有一個父類,如果繼承了Thread類就無法再繼承其他類了,顯然使用Runnable接口更為靈活。?

?

?補充:Java 5以后創建線程還有第三種方式:實現Callable接口,該接口中的call方法可以在線程執行結束時產生一個返回值,代碼如下所示:?

?

import java.util.ArrayList;

import java.util.List;

import java.util.concurrent.Callable;

import java.util.concurrent.ExecutorService;

import java.util.concurrent.Executors;

import java.util.concurrent.Future;

?

?

class MyTask implements Callable<Integer> {

? ? private int upperBounds;

?

? ? public MyTask(int upperBounds) {

? ? ? ? this.upperBounds = upperBounds;

? ? }

?

? ? @Override

? ? public Integer call() throws Exception {

? ? ? ? int sum = 0;?

? ? ? ? for(int i = 1; i <= upperBounds; i++) {

? ? ? ? ? ? sum += i;

? ? ? ? }

? ? ? ? return sum;

? ? }

?

}

?

class Test {

?

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

? ? ? ? List<Future<Integer>> list = new ArrayList<>();

? ? ? ? ExecutorService service = Executors.newFixedThreadPool(10);

? ? ? ? for(int i = 0; i < 10; i++) {

? ? ? ? ? ? list.add(service.submit(new MyTask((int) (Math.random() * 100))));

? ? ? ? }

?

? ? ? ? int sum = 0;

? ? ? ? for(Future<Integer> future : list) {

? ? ? ? ? ? // while(!future.isDone()) ;

? ? ? ? ? ? sum += future.get();

? ? ? ? }

?

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

? ? }

}?

62、synchronized關鍵字的用法?? 答:synchronized關鍵字可以將對象或者方法標記為同步,以實現對對象和方法的互斥訪問,可以用synchronized(對象) { … }定義同步代碼塊,或者在聲明方法時將synchronized作為方法的修飾符。在第60題的例子中已經展示了synchronized關鍵字的用法。?

63、舉例說明同步和異步。? 答:如果系統中存在臨界資源(資源數量少于競爭資源的線程數量的資源),例如正在寫的數據以后可能被另一個線程讀到,或者正在讀的數據可能已經被另一個線程寫過了,那么這些數據就必須進行同步存取(數據庫操作中的排他鎖就是最好的例子)。當應用程序在對象上調用了一個需要花費很長時間來執行的方法,并且不希望讓程序等待方法的返回時,就應該使用異步編程,在很多情況下采用異步途徑往往更有效率。事實上,所謂的同步就是指阻塞式操作,而異步就是非阻塞式操作。?

64、啟動一個線程是調用run()還是start()方法?? 答:啟動一個線程是調用start()方法,使線程所代表的虛擬處理機處于可運行狀態,這意味著它可以由JVM 調度并執行,這并不意味著線程就會立即運行。run()方法是線程啟動后要進行回調(callback)的方法。?

65、什么是線程池(thread pool)?? 答:在面向對象編程中,創建和銷毀對象是很費時間的,因為創建一個對象要獲取內存資源或者其它更多資源。在Java中更是如此,虛擬機將試圖跟蹤每一個對象,以便能夠在對象銷毀后進行垃圾回收。所以提高服務程序效率的一個手段就是盡可能減少創建和銷毀對象的次數,特別是一些很耗資源的對象創建和銷毀,這就是”池化資源”技術產生的原因。線程池顧名思義就是事先創建若干個可執行的線程放入一個池(容器)中,需要的時候從池中獲取線程不用自行創建,使用完畢不需要銷毀線程而是放回池中,從而減少創建和銷毀線程對象的開銷。? Java 5+中的Executor接口定義一個執行線程的工具。它的子類型即線程池接口是ExecutorService。要配置一個線程池是比較復雜的,尤其是對于線程池的原理不是很清楚的情況下,因此在工具類Executors面提供了一些靜態工廠方法,生成一些常用的線程池,如下所示:? - newSingleThreadExecutor:創建一個單線程的線程池。這個線程池只有一個線程在工作,也就是相當于單線程串行執行所有任務。如果這個唯一的線程因為異常結束,那么會有一個新的線程來替代它。此線程池保證所有任務的執行順序按照任務的提交順序執行。? - newFixedThreadPool:創建固定大小的線程池。每次提交一個任務就創建一個線程,直到線程達到線程池的最大大小。線程池的大小一旦達到最大值就會保持不變,如果某個線程因為執行異常而結束,那么線程池會補充一個新線程。? - newCachedThreadPool:創建一個可緩存的線程池。如果線程池的大小超過了處理任務所需要的線程,那么就會回收部分空閑(60秒不執行任務)的線程,當任務數增加時,此線程池又可以智能的添加新線程來處理任務。此線程池不會對線程池大小做限制,線程池大小完全依賴于操作系統(或者說JVM)能夠創建的最大線程大小。? - newScheduledThreadPool:創建一個大小無限的線程池。此線程池支持定時以及周期性執行任務的需求。? - newSingleThreadExecutor:創建一個單線程的線程池。此線程池支持定時以及周期性執行任務的需求。?

第60題的例子中演示了通過Executors工具類創建線程池并使用線程池執行線程的代碼。如果希望在服務器上使用線程池,強烈建議使用newFixedThreadPool方法來創建線程池,這樣能獲得更好的性能。?

66、線程的基本狀態以及狀態之間的關系?? 答:? ?

?

?說明:其中Running表示運行狀態,Runnable表示就緒狀態(萬事俱備,只欠CPU),Blocked表示阻塞狀態,阻塞狀態又有多種情況,可能是因為調用wait()方法進入等待池,也可能是執行同步方法或同步代碼塊進入等鎖池,或者是調用了sleep()方法或join()方法等待休眠或其他線程結束,或是因為發生了I/O中斷。?

?

67、簡述synchronized 和java.util.concurrent.locks.Lock的異同?? 答:Lock是Java 5以后引入的新的API,和關鍵字synchronized相比主要相同點:Lock 能完成synchronized所實現的所有功能;主要不同點:Lock有比synchronized更精確的線程語義和更好的性能,而且不強制性的要求一定要獲得鎖。synchronized會自動釋放鎖,而Lock一定要求程序員手工釋放,并且最好在finally 塊中釋放(這是釋放外部資源的最好的地方)。?

68、Java中如何實現序列化,有什么意義?? 答:序列化就是一種用來處理對象流的機制,所謂對象流也就是將對象的內容進行流化。可以對流化后的對象進行讀寫操作,也可將流化后的對象傳輸于網絡之間。序列化是為了解決對象流讀寫操作時可能引發的問題(如果不進行序列化可能會存在數據亂序的問題)。? 要實現序列化,需要讓一個類實現Serializable接口,該接口是一個標識性接口,標注該類對象是可被序列化的,然后使用一個輸出流來構造一個對象輸出流并通過writeObject(Object)方法就可以將實現對象寫出(即保存其狀態);如果需要反序列化則可以用一個輸入流建立對象輸入流,然后通過readObject方法從流中讀取對象。序列化除了能夠實現對象的持久化之外,還能夠用于對象的深度克隆(可以參考第29題)。?

69、Java中有幾種類型的流?? 答:字節流和字符流。字節流繼承于InputStream、OutputStream,字符流繼承于Reader、Writer。在java.io 包中還有許多其他的流,主要是為了提高性能和使用方便。關于Java的I/O需要注意的有兩點:一是兩種對稱性(輸入和輸出的對稱性,字節和字符的對稱性);二是兩種設計模式(適配器模式和裝潢模式)。另外Java中的流不同于C#的是它只有一個維度一個方向。?

?

?面試題 - 編程實現文件拷貝。(這個題目在筆試的時候經常出現,下面的代碼給出了兩種實現方案)?

?

import java.io.FileInputStream;

import java.io.FileOutputStream;

import java.io.IOException;

import java.io.InputStream;

import java.io.OutputStream;

import java.nio.ByteBuffer;

import java.nio.channels.FileChannel;

?

public final class MyUtil {

?

? ? private MyUtil() {

? ? ? ? throw new AssertionError();

? ? }

?

? ? public static void fileCopy(String source, String target) throws IOException {

? ? ? ? try (InputStream in = new FileInputStream(source)) {

? ? ? ? ? ? try (OutputStream out = new FileOutputStream(target)) {

? ? ? ? ? ? ? ? byte[] buffer = new byte[4096];

? ? ? ? ? ? ? ? int bytesToRead;

? ? ? ? ? ? ? ? while((bytesToRead = in.read(buffer)) != -1) {

? ? ? ? ? ? ? ? ? ? out.write(buffer, 0, bytesToRead);

? ? ? ? ? ? ? ? }

? ? ? ? ? ? }

? ? ? ? }

? ? }

?

? ? public static void fileCopyNIO(String source, String target) throws IOException {

? ? ? ? try (FileInputStream in = new FileInputStream(source)) {

? ? ? ? ? ? try (FileOutputStream out = new FileOutputStream(target)) {

? ? ? ? ? ? ? ? FileChannel inChannel = in.getChannel();

? ? ? ? ? ? ? ? FileChannel outChannel = out.getChannel();

? ? ? ? ? ? ? ? ByteBuffer buffer = ByteBuffer.allocate(4096);

? ? ? ? ? ? ? ? while(inChannel.read(buffer) != -1) {

? ? ? ? ? ? ? ? ? ? buffer.flip();

? ? ? ? ? ? ? ? ? ? outChannel.write(buffer);

? ? ? ? ? ? ? ? ? ? buffer.clear();

? ? ? ? ? ? ? ? }

? ? ? ? ? ? }

? ? ? ? }

? ? }

}?

?

?注意:上面用到Java 7的TWR,使用TWR后可以不用在finally中釋放外部資源 ,從而讓代碼更加優雅。?

?

70、寫一個方法,輸入一個文件名和一個字符串,統計這個字符串在這個文件中出現的次數。? 答:代碼如下:?

import java.io.BufferedReader;

import java.io.FileReader;

?

public final class MyUtil {

?

? ? // 工具類中的方法都是靜態方式訪問的因此將構造器私有不允許創建對象(絕對好習慣)

? ? private MyUtil() {

? ? ? ? throw new AssertionError();

? ? }

?

? ? /**

? ? ?* 統計給定文件中給定字符串的出現次數

? ? ?*?

? ? ?* @param filename? 文件名

? ? ?* @param word 字符串

? ? ?* @return 字符串在文件中出現的次數

? ? ?*/

? ? public static int countWordInFile(String filename, String word) {

? ? ? ? int counter = 0;

? ? ? ? try (FileReader fr = new FileReader(filename)) {

? ? ? ? ? ? try (BufferedReader br = new BufferedReader(fr)) {

? ? ? ? ? ? ? ? String line = null;

? ? ? ? ? ? ? ? while ((line = br.readLine()) != null) {

? ? ? ? ? ? ? ? ? ? int index = -1;

? ? ? ? ? ? ? ? ? ? while (line.length() >= word.length() && (index = line.indexOf(word)) >= 0) {

? ? ? ? ? ? ? ? ? ? ? ? counter++;

? ? ? ? ? ? ? ? ? ? ? ? line = line.substring(index + word.length());

? ? ? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? }

? ? ? ? ? ? }

? ? ? ? } catch (Exception ex) {

? ? ? ? ? ? ex.printStackTrace();

? ? ? ? }

? ? ? ? return counter;

? ? }

?

}?

71、如何用Java代碼列出一個目錄下所有的文件?? 答:? 如果只要求列出當前文件夾下的文件,代碼如下所示:?

import java.io.File;

?

class Test12 {

?

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

? ? ? ? File f = new File("/Users/Hao/Downloads");

? ? ? ? for(File temp : f.listFiles()) {

? ? ? ? ? ? if(temp.isFile()) {

? ? ? ? ? ? ? ? System.out.println(temp.getName());

? ? ? ? ? ? }

? ? ? ? }

? ? }

}?

如果需要對文件夾繼續展開,代碼如下所示:?

import java.io.File;

?

class Test12 {

?

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

? ? ? ? showDirectory(new File("/Users/Hao/Downloads"));

? ? }

?

? ? public static void showDirectory(File f) {

? ? ? ? _walkDirectory(f, 0);

? ? }

?

? ? private static void _walkDirectory(File f, int level) {

? ? ? ? if(f.isDirectory()) {

? ? ? ? ? ? for(File temp : f.listFiles()) {

? ? ? ? ? ? ? ? _walkDirectory(temp, level + 1);

? ? ? ? ? ? }

? ? ? ? }

? ? ? ? else {

? ? ? ? ? ? for(int i = 0; i < level - 1; i++) {

? ? ? ? ? ? ? ? System.out.print("\t");

? ? ? ? ? ? }

? ? ? ? ? ? System.out.println(f.getName());

? ? ? ? }

? ? }

}?

在Java 7中可以使用NIO.2的API來做同樣的事情,代碼如下所示:?

class ShowFileTest {

?

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

? ? ? ? Path initPath = Paths.get("/Users/Hao/Downloads");

? ? ? ? Files.walkFileTree(initPath, new SimpleFileVisitor<Path>() {

?

? ? ? ? ? ? @Override

? ? ? ? ? ? public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)?

? ? ? ? ? ? ? ? ? ? throws IOException {

? ? ? ? ? ? ? ? System.out.println(file.getFileName().toString());

? ? ? ? ? ? ? ? return FileVisitResult.CONTINUE;

? ? ? ? ? ? }

?

? ? ? ? });

? ? }

}?

72、用Java的套接字編程實現一個多線程的回顯(echo)服務器。? 答:?

import java.io.BufferedReader;

import java.io.IOException;

import java.io.InputStreamReader;

import java.io.PrintWriter;

import java.net.ServerSocket;

import java.net.Socket;

?

public class EchoServer {

?

? ? private static final int ECHO_SERVER_PORT = 6789;

?

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

? ? ? ? try(ServerSocket server = new ServerSocket(ECHO_SERVER_PORT)) {

? ? ? ? ? ? System.out.println("服務器已經啟動...");

? ? ? ? ? ? while(true) {

? ? ? ? ? ? ? ? Socket client = server.accept();

? ? ? ? ? ? ? ? new Thread(new ClientHandler(client)).start();

? ? ? ? ? ? }

? ? ? ? } catch (IOException e) {

? ? ? ? ? ? e.printStackTrace();

? ? ? ? }

? ? }

?

? ? private static class ClientHandler implements Runnable {

? ? ? ? private Socket client;

?

? ? ? ? public ClientHandler(Socket client) {

? ? ? ? ? ? this.client = client;

? ? ? ? }

?

? ? ? ? @Override

? ? ? ? public void run() {

? ? ? ? ? ? try(BufferedReader br = new BufferedReader(new InputStreamReader(client.getInputStream()));

? ? ? ? ? ? ? ? ? ? PrintWriter pw = new PrintWriter(client.getOutputStream())) {

? ? ? ? ? ? ? ? String msg = br.readLine();

? ? ? ? ? ? ? ? System.out.println("收到" + client.getInetAddress() + "發送的: " + msg);

? ? ? ? ? ? ? ? pw.println(msg);

? ? ? ? ? ? ? ? pw.flush();

? ? ? ? ? ? } catch(Exception ex) {

? ? ? ? ? ? ? ? ex.printStackTrace();

? ? ? ? ? ? } finally {

? ? ? ? ? ? ? ? try {

? ? ? ? ? ? ? ? ? ? client.close();

? ? ? ? ? ? ? ? } catch (IOException e) {

? ? ? ? ? ? ? ? ? ? e.printStackTrace();

? ? ? ? ? ? ? ? }

? ? ? ? ? ? }

? ? ? ? }

? ? }

?

}?

?

?注意:上面的代碼使用了Java 7的TWR語法,由于很多外部資源類都間接的實現了AutoCloseable接口(單方法回調接口),因此可以利用TWR語法在try結束的時候通過回調的方式自動調用外部資源類的close()方法,避免書寫冗長的finally代碼塊。此外,上面的代碼用一個靜態內部類實現線程的功能,使用多線程可以避免一個用戶I/O操作所產生的中斷影響其他用戶對服務器的訪問,簡單的說就是一個用戶的輸入操作不會造成其他用戶的阻塞。當然,上面的代碼使用線程池可以獲得更好的性能,因為頻繁的創建和銷毀線程所造成的開銷也是不可忽視的。?

?

下面是一段回顯客戶端測試代碼:?

import java.io.BufferedReader;

import java.io.InputStreamReader;

import java.io.PrintWriter;

import java.net.Socket;

import java.util.Scanner;

?

public class EchoClient {

?

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

? ? ? ? Socket client = new Socket("localhost", 6789);

? ? ? ? Scanner sc = new Scanner(System.in);

? ? ? ? System.out.print("請輸入內容: ");

? ? ? ? String msg = sc.nextLine();

? ? ? ? sc.close();

? ? ? ? PrintWriter pw = new PrintWriter(client.getOutputStream());

? ? ? ? pw.println(msg);

? ? ? ? pw.flush();

? ? ? ? BufferedReader br = new BufferedReader(new InputStreamReader(client.getInputStream()));

? ? ? ? System.out.println(br.readLine());

? ? ? ? client.close();

? ? }

}?

如果希望用NIO的多路復用套接字實現服務器,代碼如下所示。NIO的操作雖然帶來了更好的性能,但是有些操作是比較底層的,對于初學者來說還是有些難于理解。?

import java.io.IOException;

import java.net.InetSocketAddress;

import java.nio.ByteBuffer;

import java.nio.CharBuffer;

import java.nio.channels.SelectionKey;

import java.nio.channels.Selector;

import java.nio.channels.ServerSocketChannel;

import java.nio.channels.SocketChannel;

import java.util.Iterator;

?

public class EchoServerNIO {

?

? ? private static final int ECHO_SERVER_PORT = 6789;

? ? private static final int ECHO_SERVER_TIMEOUT = 5000;

? ? private static final int BUFFER_SIZE = 1024;

?

? ? private static ServerSocketChannel serverChannel = null;

? ? private static Selector selector = null;? ? // 多路復用選擇器

? ? private static ByteBuffer buffer = null;? ? // 緩沖區

?

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

? ? ? ? init();

? ? ? ? listen();

? ? }

?

? ? private static void init() {

? ? ? ? try {

? ? ? ? ? ? serverChannel = ServerSocketChannel.open();

? ? ? ? ? ? buffer = ByteBuffer.allocate(BUFFER_SIZE);

? ? ? ? ? ? serverChannel.socket().bind(new InetSocketAddress(ECHO_SERVER_PORT));

? ? ? ? ? ? serverChannel.configureBlocking(false);

? ? ? ? ? ? selector = Selector.open();

? ? ? ? ? ? serverChannel.register(selector, SelectionKey.OP_ACCEPT);

? ? ? ? } catch (Exception e) {

? ? ? ? ? ? throw new RuntimeException(e);

? ? ? ? }

? ? }

?

? ? private static void listen() {

? ? ? ? while (true) {

? ? ? ? ? ? try {

? ? ? ? ? ? ? ? if (selector.select(ECHO_SERVER_TIMEOUT) != 0) {

? ? ? ? ? ? ? ? ? ? Iterator<SelectionKey> it = selector.selectedKeys().iterator();

? ? ? ? ? ? ? ? ? ? while (it.hasNext()) {

? ? ? ? ? ? ? ? ? ? ? ? SelectionKey key = it.next();

? ? ? ? ? ? ? ? ? ? ? ? it.remove();

? ? ? ? ? ? ? ? ? ? ? ? handleKey(key);

? ? ? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? }

? ? ? ? ? ? } catch (Exception e) {

? ? ? ? ? ? ? ? e.printStackTrace();

? ? ? ? ? ? }

? ? ? ? }

? ? }

?

? ? private static void handleKey(SelectionKey key) throws IOException {

? ? ? ? SocketChannel channel = null;

?

? ? ? ? try {

? ? ? ? ? ? if (key.isAcceptable()) {

? ? ? ? ? ? ? ? ServerSocketChannel serverChannel = (ServerSocketChannel) key.channel();

? ? ? ? ? ? ? ? channel = serverChannel.accept();

? ? ? ? ? ? ? ? channel.configureBlocking(false);

? ? ? ? ? ? ? ? channel.register(selector, SelectionKey.OP_READ);

? ? ? ? ? ? } else if (key.isReadable()) {

? ? ? ? ? ? ? ? channel = (SocketChannel) key.channel();

? ? ? ? ? ? ? ? buffer.clear();

? ? ? ? ? ? ? ? if (channel.read(buffer) > 0) {

? ? ? ? ? ? ? ? ? ? buffer.flip();

? ? ? ? ? ? ? ? ? ? CharBuffer charBuffer = CharsetHelper.decode(buffer);

? ? ? ? ? ? ? ? ? ? String msg = charBuffer.toString();

? ? ? ? ? ? ? ? ? ? System.out.println("收到" + channel.getRemoteAddress() + "的消息:" + msg);

? ? ? ? ? ? ? ? ? ? channel.write(CharsetHelper.encode(CharBuffer.wrap(msg)));

? ? ? ? ? ? ? ? } else {

? ? ? ? ? ? ? ? ? ? channel.close();

? ? ? ? ? ? ? ? }

? ? ? ? ? ? }

? ? ? ? } catch (Exception e) {

? ? ? ? ? ? e.printStackTrace();

? ? ? ? ? ? if (channel != null) {

? ? ? ? ? ? ? ? channel.close();

? ? ? ? ? ? }

? ? ? ? }

? ? }

?

}?

import java.nio.ByteBuffer;

import java.nio.CharBuffer;

import java.nio.charset.CharacterCodingException;

import java.nio.charset.Charset;

import java.nio.charset.CharsetDecoder;

import java.nio.charset.CharsetEncoder;

?

public final class CharsetHelper {

? ? private static final String UTF_8 = "UTF-8";

? ? private static CharsetEncoder encoder = Charset.forName(UTF_8).newEncoder();

? ? private static CharsetDecoder decoder = Charset.forName(UTF_8).newDecoder();

?

? ? private CharsetHelper() {

? ? }

?

? ? public static ByteBuffer encode(CharBuffer in) throws CharacterCodingException{

? ? ? ? return encoder.encode(in);

? ? }

?

? ? public static CharBuffer decode(ByteBuffer in) throws CharacterCodingException{

? ? ? ? return decoder.decode(in);

? ? }

}?

73、XML文檔定義有幾種形式?它們之間有何本質區別?解析XML文檔有哪幾種方式?? 答:XML文檔定義分為DTD和Schema兩種形式,二者都是對XML語法的約束,其本質區別在于Schema本身也是一個XML文件,可以被XML解析器解析,而且可以為XML承載的數據定義類型,約束能力較之DTD更強大。對XML的解析主要有DOM(文檔對象模型,Document Object Model)、SAX(Simple API for XML)和StAX(Java 6中引入的新的解析XML的方式,Streaming API for XML),其中DOM處理大型文件時其性能下降的非常厲害,這個問題是由DOM樹結構占用的內存較多造成的,而且DOM解析方式必須在解析文件之前把整個文檔裝入內存,適合對XML的隨機訪問(典型的用空間換取時間的策略);SAX是事件驅動型的XML解析方式,它順序讀取XML文件,不需要一次全部裝載整個文件。當遇到像文件開頭,文檔結束,或者標簽開頭與標簽結束時,它會觸發一個事件,用戶通過事件回調代碼來處理XML文件,適合對XML的順序訪問;顧名思義,StAX把重點放在流上,實際上StAX與其他解析方式的本質區別就在于應用程序能夠把XML作為一個事件流來處理。將XML作為一組事件來處理的想法并不新穎(SAX就是這樣做的),但不同之處在于StAX允許應用程序代碼把這些事件逐個拉出來,而不用提供在解析器方便時從解析器中接收事件的處理程序。?

74、你在項目中哪些地方用到了XML?? 答:XML的主要作用有兩個方面:數據交換和信息配置。在做數據交換時,XML將數據用標簽組裝成起來,然后壓縮打包加密后通過網絡傳送給接收者,接收解密與解壓縮后再從XML文件中還原相關信息進行處理,XML曾經是異構系統間交換數據的事實標準,但此項功能幾乎已經被JSON(JavaScript Object Notation)取而代之。當然,目前很多軟件仍然使用XML來存儲配置信息,我們在很多項目中通常也會將作為配置信息的硬代碼寫在XML文件中,Java的很多框架也是這么做的,而且這些框架都選擇了dom4j作為處理XML的工具,因為Sun公司的官方API實在不怎么好用。?

?

?補充:現在有很多時髦的軟件(如Sublime)已經開始將配置文件書寫成JSON格式,我們已經強烈的感受到XML的另一項功能也將逐漸被業界拋棄。?

?

75、闡述JDBC操作數據庫的步驟。? 答:下面的代碼以連接本機的Oracle數據庫為例,演示JDBC操作數據庫的步驟。?

加載驅動。?

? ? Class.forName("oracle.jdbc.driver.OracleDriver");?

創建連接。?

? ? Connection con = DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:orcl", "scott", "tiger");?

創建語句。?

? ? PreparedStatement ps = con.prepareStatement("select * from emp where sal between ? and ?");

? ? ps.setInt(1, 1000);

? ? ps.setInt(2, 3000);?

執行語句。?

? ? ResultSet rs = ps.executeQuery();?

處理結果。?

? ? while(rs.next()) {

? ? ? ? System.out.println(rs.getInt("empno") + " - " + rs.getString("ename"));

? ? }?

關閉資源。?

? ? finally {

? ? ? ? if(con != null) {

? ? ? ? ? ? try {

? ? ? ? ? ? ? ? con.close();

? ? ? ? ? ? } catch (SQLException e) {

? ? ? ? ? ? ? ? e.printStackTrace();

? ? ? ? ? ? }

? ? ? ? }

? ? }?

?

?提示:關閉外部資源的順序應該和打開的順序相反,也就是說先關閉ResultSet、再關閉Statement、在關閉Connection。上面的代碼只關閉了Connection(連接),雖然通常情況下在關閉連接時,連接上創建的語句和打開的游標也會關閉,但不能保證總是如此,因此應該按照剛才說的順序分別關閉。此外,第一步加載驅動在JDBC 4.0中是可以省略的(自動從類路徑中加載驅動),但是我們建議保留。?

?

76、Statement和PreparedStatement有什么區別?哪個性能更好?? 答:與Statement相比,①PreparedStatement接口代表預編譯的語句,它主要的優勢在于可以減少SQL的編譯錯誤并增加SQL的安全性(減少SQL注射攻擊的可能性);②PreparedStatement中的SQL語句是可以帶參數的,避免了用字符串連接拼接SQL語句的麻煩和不安全;③當批量處理SQL或頻繁執行相同的查詢時,PreparedStatement有明顯的性能上的優勢,由于數據庫可以將編譯優化后的SQL語句緩存起來,下次執行相同結構的語句時就會很快(不用再次編譯和生成執行計劃)。?

?

?補充:為了提供對存儲過程的調用,JDBC API中還提供了CallableStatement接口。存儲過程(Stored Procedure)是數據庫中一組為了完成特定功能的SQL語句的集合,經編譯后存儲在數據庫中,用戶通過指定存儲過程的名字并給出參數(如果該存儲過程帶有參數)來執行它。雖然調用存儲過程會在網絡開銷、安全性、性能上獲得很多好處,但是存在如果底層數據庫發生遷移時就會有很多麻煩,因為每種數據庫的存儲過程在書寫上存在不少的差別。?

?

77、使用JDBC操作數據庫時,如何提升讀取數據的性能?如何提升更新數據的性能?? 答:要提升讀取數據的性能,可以指定通過結果集(ResultSet)對象的setFetchSize()方法指定每次抓取的記錄數(典型的空間換時間策略);要提升更新數據的性能可以使用PreparedStatement語句構建批處理,將若干SQL語句置于一個批處理中執行。?

78、在進行數據庫編程時,連接池有什么作用?? 答:由于創建連接和釋放連接都有很大的開銷(尤其是數據庫服務器不在本地時,每次建立連接都需要進行TCP的三次握手,釋放連接需要進行TCP四次握手,造成的開銷是不可忽視的),為了提升系統訪問數據庫的性能,可以事先創建若干連接置于連接池中,需要時直接從連接池獲取,使用結束時歸還連接池而不必關閉連接,從而避免頻繁創建和釋放連接所造成的開銷,這是典型的用空間換取時間的策略(浪費了空間存儲連接,但節省了創建和釋放連接的時間)。池化技術在Java開發中是很常見的,在使用線程時創建線程池的道理與此相同。基于Java的開源數據庫連接池主要有:C3P0、Proxool、DBCP、BoneCP、Druid等。?

?

?補充:在計算機系統中時間和空間是不可調和的矛盾,理解這一點對設計滿足性能要求的算法是至關重要的。大型網站性能優化的一個關鍵就是使用緩存,而緩存跟上面講的連接池道理非常類似,也是使用空間換時間的策略。可以將熱點數據置于緩存中,當用戶查詢這些數據時可以直接從緩存中得到,這無論如何也快過去數據庫中查詢。當然,緩存的置換策略等也會對系統性能產生重要影響,對于這個問題的討論已經超出了這里要闡述的范圍。?

?

79、什么是DAO模式?? 答:DAO(Data Access Object)顧名思義是一個為數據庫或其他持久化機制提供了抽象接口的對象,在不暴露底層持久化方案實現細節的前提下提供了各種數據訪問操作。在實際的開發中,應該將所有對數據源的訪問操作進行抽象化后封裝在一個公共API中。用程序設計語言來說,就是建立一個接口,接口中定義了此應用程序中將會用到的所有事務方法。在這個應用程序中,當需要和數據源進行交互的時候則使用這個接口,并且編寫一個單獨的類來實現這個接口,在邏輯上該類對應一個特定的數據存儲。DAO模式實際上包含了兩個模式,一是Data Accessor(數據訪問器),二是Data Object(數據對象),前者要解決如何訪問數據的問題,而后者要解決的是如何用對象封裝數據。?

80、事務的ACID是指什么?? 答:? - 原子性(Atomic):事務中各項操作,要么全做要么全不做,任何一項操作的失敗都會導致整個事務的失敗;? - 一致性(Consistent):事務結束后系統狀態是一致的;? - 隔離性(Isolated):并發執行的事務彼此無法看到對方的中間狀態;? - 持久性(Durable):事務完成后所做的改動都會被持久化,即使發生災難性的失敗。通過日志和同步備份可以在故障發生后重建數據。?

?

?補充:關于事務,在面試中被問到的概率是很高的,可以問的問題也是很多的。首先需要知道的是,只有存在并發數據訪問時才需要事務。當多個事務訪問同一數據時,可能會存在5類問題,包括3類數據讀取問題(臟讀、不可重復讀和幻讀)和2類數據更新問題(第1類丟失更新和第2類丟失更新)。?

?

臟讀(Dirty Read):A事務讀取B事務尚未提交的數據并在此基礎上操作,而B事務執行回滾,那么A讀取到的數據就是臟數據。?

時間轉賬事務A取款事務BT1 開始事務T2開始事務 T3 查詢賬戶余額為1000元T4 取出500元余額修改為500元T5查詢賬戶余額為500元(臟讀) T6 撤銷事務余額恢復為1000元T7匯入100元把余額修改為600元 T8提交事務??

?

不可重復讀(Unrepeatable Read):事務A重新讀取前面讀取過的數據,發現該數據已經被另一個已提交的事務B修改過了。?

時間轉賬事務A取款事務BT1 開始事務T2開始事務 T3 查詢賬戶余額為1000元T4查詢賬戶余額為1000元 T5 取出100元修改余額為900元T6 提交事務T7查詢賬戶余額為900元(不可重復讀)??

?

幻讀(Phantom Read):事務A重新執行一個查詢,返回一系列符合查詢條件的行,發現其中插入了被事務B提交的行。?

時間統計金額事務A轉賬事務BT1 開始事務T2開始事務 T3統計總存款為10000元 T4 新增一個存款賬戶存入100元T5 提交事務T6再次統計總存款為10100元(幻讀)??

?

第1類丟失更新:事務A撤銷時,把已經提交的事務B的更新數據覆蓋了。?

時間取款事務A轉賬事務BT1開始事務 T2 開始事務T3查詢賬戶余額為1000元 T4 查詢賬戶余額為1000元T5 匯入100元修改余額為1100元T6 提交事務T7取出100元將余額修改為900元 T8撤銷事務 T9余額恢復為1000元(丟失更新)??

?

第2類丟失更新:事務A覆蓋事務B已經提交的數據,造成事務B所做的操作丟失。?

時間轉賬事務A取款事務BT1 開始事務T2開始事務 T3 查詢賬戶余額為1000元T4查詢賬戶余額為1000元 T5 取出100元將余額修改為900元T6 提交事務T7匯入100元將余額修改為1100元 T8提交事務 T9查詢賬戶余額為1100元(丟失更新)??

?

數據并發訪問所產生的問題,在有些場景下可能是允許的,但是有些場景下可能就是致命的,數據庫通常會通過鎖機制來解決數據并發訪問問題,按鎖定對象不同可以分為表級鎖和行級鎖;按并發事務鎖定關系可以分為共享鎖和獨占鎖,具體的內容大家可以自行查閱資料進行了解。? 直接使用鎖是非常麻煩的,為此數據庫為用戶提供了自動鎖機制,只要用戶指定會話的事務隔離級別,數據庫就會通過分析SQL語句然后為事務訪問的資源加上合適的鎖,此外,數據庫還會維護這些鎖通過各種手段提高系統的性能,這些對用戶來說都是透明的(就是說你不用理解,事實上我確實也不知道)。ANSI/ISO SQL 92標準定義了4個等級的事務隔離級別,如下表所示:?

隔離級別臟讀不可重復讀幻讀第一類丟失更新第二類丟失更新READ UNCOMMITED允許允許允許不允許允許READ COMMITTED不允許允許允許不允許允許REPEATABLE READ不允許不允許允許不允許不允許SERIALIZABLE不允許不允許不允許不允許不允許?

需要說明的是,事務隔離級別和數據訪問的并發性是對立的,事務隔離級別越高并發性就越差。所以要根據具體的應用來確定合適的事務隔離級別,這個地方沒有萬能的原則。?

81、JDBC中如何進行事務處理?? 答:Connection提供了事務處理的方法,通過調用setAutoCommit(false)可以設置手動提交事務;當事務完成后用commit()顯式提交事務;如果在事務處理過程中發生異常則通過rollback()進行事務回滾。除此之外,從JDBC 3.0中還引入了Savepoint(保存點)的概念,允許通過代碼設置保存點并讓事務回滾到指定的保存點。? ?

82、JDBC能否處理Blob和Clob?? 答: Blob是指二進制大對象(Binary Large Object),而Clob是指大字符對象(Character Large Objec),因此其中Blob是為存儲大的二進制數據而設計的,而Clob是為存儲大的文本數據而設計的。JDBC的PreparedStatement和ResultSet都提供了相應的方法來支持Blob和Clob操作。下面的代碼展示了如何使用JDBC操作LOB:? 下面以MySQL數據庫為例,創建一個張有三個字段的用戶表,包括編號(id)、姓名(name)和照片(photo),建表語句如下:?

create table tb_user

(

id int primary key auto_increment,

name varchar(20) unique not null,

photo longblob

);?

下面的Java代碼向數據庫中插入一條記錄:?

import java.io.FileInputStream;

import java.io.IOException;

import java.io.InputStream;

import java.sql.Connection;

import java.sql.DriverManager;

import java.sql.PreparedStatement;

import java.sql.SQLException;

?

class JdbcLobTest {

?

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

? ? ? ? Connection con = null;

? ? ? ? try {

? ? ? ? ? ? // 1. 加載驅動(Java6以上版本可以省略)

? ? ? ? ? ? Class.forName("com.mysql.jdbc.Driver");

? ? ? ? ? ? // 2. 建立連接

? ? ? ? ? ? con = DriverManager.getConnection("jdbc:mysql://localhost:3306/test", "root", "123456");

? ? ? ? ? ? // 3. 創建語句對象

? ? ? ? ? ? PreparedStatement ps = con.prepareStatement("insert into tb_user values (default, ?, ?)");

? ? ? ? ? ? ps.setString(1, "駱昊");? ? ? ? ? ? ? // 將SQL語句中第一個占位符換成字符串

? ? ? ? ? ? try (InputStream in = new FileInputStream("test.jpg")) {? ? // Java 7的TWR

? ? ? ? ? ? ? ? ps.setBinaryStream(2, in);? ? ? // 將SQL語句中第二個占位符換成二進制流

? ? ? ? ? ? ? ? // 4. 發出SQL語句獲得受影響行數

? ? ? ? ? ? ? ? System.out.println(ps.executeUpdate() == 1 ? "插入成功" : "插入失敗");

? ? ? ? ? ? } catch(IOException e) {

? ? ? ? ? ? ? ? System.out.println("讀取照片失敗!");

? ? ? ? ? ? }

? ? ? ? } catch (ClassNotFoundException | SQLException e) {? ? ?// Java 7的多異常捕獲

? ? ? ? ? ? e.printStackTrace();

? ? ? ? } finally { // 釋放外部資源的代碼都應當放在finally中保證其能夠得到執行

? ? ? ? ? ? try {

? ? ? ? ? ? ? ? if(con != null && !con.isClosed()) {

? ? ? ? ? ? ? ? ? ? con.close();? ? // 5. 釋放數據庫連接?

? ? ? ? ? ? ? ? ? ? con = null;? ? ?// 指示垃圾回收器可以回收該對象

? ? ? ? ? ? ? ? }

? ? ? ? ? ? } catch (SQLException e) {

? ? ? ? ? ? ? ? e.printStackTrace();

? ? ? ? ? ? }

? ? ? ? }

? ? }

}?

83、簡述正則表達式及其用途。? 答:在編寫處理字符串的程序時,經常會有查找符合某些復雜規則的字符串的需要。正則表達式就是用于描述這些規則的工具。換句話說,正則表達式就是記錄文本規則的代碼。?

?

?說明:計算機誕生初期處理的信息幾乎都是數值,但是時過境遷,今天我們使用計算機處理的信息更多的時候不是數值而是字符串,正則表達式就是在進行字符串匹配和處理的時候最為強大的工具,絕大多數語言都提供了對正則表達式的支持。?

?

84、Java中是如何支持正則表達式操作的?? 答:Java中的String類提供了支持正則表達式操作的方法,包括:matches()、replaceAll()、replaceFirst()、split()。此外,Java中可以用Pattern類表示正則表達式對象,它提供了豐富的API進行各種正則表達式操作,請參考下面面試題的代碼。?

?

?面試題: - 如果要從字符串中截取第一個英文左括號之前的字符串,例如:北京市(朝陽區)(西城區)(海淀區),截取結果為:北京市,那么正則表達式怎么寫??

?

import java.util.regex.Matcher;

import java.util.regex.Pattern;

?

class RegExpTest {

?

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

? ? ? ? String str = "北京市(朝陽區)(西城區)(海淀區)";

? ? ? ? Pattern p = Pattern.compile(".*?(?=\\()");

? ? ? ? Matcher m = p.matcher(str);

? ? ? ? if(m.find()) {

? ? ? ? ? ? System.out.println(m.group());

? ? ? ? }

? ? }

}?

?

?說明:上面的正則表達式中使用了懶惰匹配和前瞻,如果不清楚這些內容,推薦讀一下網上很有名的《正則表達式30分鐘入門教程》。?

?

85、獲得一個類的類對象有哪些方式?? 答:? - 方法1:類型.class,例如:String.class? - 方法2:對象.getClass(),例如:"hello".getClass()? - 方法3:Class.forName(),例如:Class.forName("java.lang.String")?

86、如何通過反射創建對象?? 答:? - 方法1:通過類對象調用newInstance()方法,例如:String.class.newInstance()? - 方法2:通過類對象的getConstructor()或getDeclaredConstructor()方法獲得構造器(Constructor)對象并調用其newInstance()方法創建對象,例如:String.class.getConstructor(String.class).newInstance("Hello");?

87、如何通過反射獲取和設置對象私有字段的值?? 答:可以通過類對象的getDeclaredField()方法字段(Field)對象,然后再通過字段對象的setAccessible(true)將其設置為可以訪問,接下來就可以通過get/set方法來獲取/設置字段的值了。下面的代碼實現了一個反射的工具類,其中的兩個靜態方法分別用于獲取和設置私有字段的值,字段可以是基本類型也可以是對象類型且支持多級對象操作,例如ReflectionUtil.get(dog, "owner.car.engine.id");可以獲得dog對象的主人的汽車的引擎的ID號。?

import java.lang.reflect.Constructor;

import java.lang.reflect.Field;

import java.lang.reflect.Modifier;

import java.util.ArrayList;

import java.util.List;

?

/**

?* 反射工具類

?* @author 駱昊

?*

?*/

public class ReflectionUtil {

?

? ? private ReflectionUtil() {

? ? ? ? throw new AssertionError();

? ? }

?

? ? /**

? ? ?* 通過反射取對象指定字段(屬性)的值

? ? ?* @param target 目標對象

? ? ?* @param fieldName 字段的名字

? ? ?* @throws 如果取不到對象指定字段的值則拋出異常

? ? ?* @return 字段的值

? ? ?*/

? ? public static Object getValue(Object target, String fieldName) {

? ? ? ? Class<?> clazz = target.getClass();

? ? ? ? String[] fs = fieldName.split("\\.");

?

? ? ? ? try {

? ? ? ? ? ? for(int i = 0; i < fs.length - 1; i++) {

? ? ? ? ? ? ? ? Field f = clazz.getDeclaredField(fs[i]);

? ? ? ? ? ? ? ? f.setAccessible(true);

? ? ? ? ? ? ? ? target = f.get(target);

? ? ? ? ? ? ? ? clazz = target.getClass();

? ? ? ? ? ? }

?

? ? ? ? ? ? Field f = clazz.getDeclaredField(fs[fs.length - 1]);

? ? ? ? ? ? f.setAccessible(true);

? ? ? ? ? ? return f.get(target);

? ? ? ? }

? ? ? ? catch (Exception e) {

? ? ? ? ? ? throw new RuntimeException(e);

? ? ? ? }

? ? }

?

? ? /**

? ? ?* 通過反射給對象的指定字段賦值

? ? ?* @param target 目標對象

? ? ?* @param fieldName 字段的名稱

? ? ?* @param value 值

? ? ?*/

? ? public static void setValue(Object target, String fieldName, Object value) {

? ? ? ? Class<?> clazz = target.getClass();

? ? ? ? String[] fs = fieldName.split("\\.");

? ? ? ? try {

? ? ? ? ? ? for(int i = 0; i < fs.length - 1; i++) {

? ? ? ? ? ? ? ? Field f = clazz.getDeclaredField(fs[i]);

? ? ? ? ? ? ? ? f.setAccessible(true);

? ? ? ? ? ? ? ? Object val = f.get(target);

? ? ? ? ? ? ? ? if(val == null) {

? ? ? ? ? ? ? ? ? ? Constructor<?> c = f.getType().getDeclaredConstructor();

? ? ? ? ? ? ? ? ? ? c.setAccessible(true);

? ? ? ? ? ? ? ? ? ? val = c.newInstance();

? ? ? ? ? ? ? ? ? ? f.set(target, val);

? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? target = val;

? ? ? ? ? ? ? ? clazz = target.getClass();

? ? ? ? ? ? }

?

? ? ? ? ? ? Field f = clazz.getDeclaredField(fs[fs.length - 1]);

? ? ? ? ? ? f.setAccessible(true);

? ? ? ? ? ? f.set(target, value);

? ? ? ? }

? ? ? ? catch (Exception e) {

? ? ? ? ? ? throw new RuntimeException(e);

? ? ? ? }

? ? }

?

}?

88、如何通過反射調用對象的方法?? 答:請看下面的代碼:?

import java.lang.reflect.Method;

?

class MethodInvokeTest {

?

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

? ? ? ? String str = "hello";

? ? ? ? Method m = str.getClass().getMethod("toUpperCase");

? ? ? ? System.out.println(m.invoke(str));? // HELLO

? ? }

}?

89、簡述一下面向對象的"六原則一法則"。? 答:? - 單一職責原則:一個類只做它該做的事情。(單一職責原則想表達的就是"高內聚",寫代碼最終極的原則只有六個字"高內聚、低耦合",就如同葵花寶典或辟邪劍譜的中心思想就八個字"欲練此功必先自宮",所謂的高內聚就是一個代碼模塊只完成一項功能,在面向對象中,如果只讓一個類完成它該做的事,而不涉及與它無關的領域就是踐行了高內聚的原則,這個類就只有單一職責。我們都知道一句話叫"因為專注,所以專業",一個對象如果承擔太多的職責,那么注定它什么都做不好。這個世界上任何好的東西都有兩個特征,一個是功能單一,好的相機絕對不是電視購物里面賣的那種一個機器有一百多種功能的,它基本上只能照相;另一個是模塊化,好的自行車是組裝車,從減震叉、剎車到變速器,所有的部件都是可以拆卸和重新組裝的,好的乒乓球拍也不是成品拍,一定是底板和膠皮可以拆分和自行組裝的,一個好的軟件系統,它里面的每個功能模塊也應該是可以輕易的拿到其他系統中使用的,這樣才能實現軟件復用的目標。)? - 開閉原則:軟件實體應當對擴展開放,對修改關閉。(在理想的狀態下,當我們需要為一個軟件系統增加新功能時,只需要從原來的系統派生出一些新類就可以,不需要修改原來的任何一行代碼。要做到開閉有兩個要點:①抽象是關鍵,一個系統中如果沒有抽象類或接口系統就沒有擴展點;②封裝可變性,將系統中的各種可變因素封裝到一個繼承結構中,如果多個可變因素混雜在一起,系統將變得復雜而換亂,如果不清楚如何封裝可變性,可以參考《設計模式精解》一書中對橋梁模式的講解的章節。)? - 依賴倒轉原則:面向接口編程。(該原則說得直白和具體一些就是聲明方法的參數類型、方法的返回類型、變量的引用類型時,盡可能使用抽象類型而不用具體類型,因為抽象類型可以被它的任何一個子類型所替代,請參考下面的里氏替換原則。)? 里氏替換原則:任何時候都可以用子類型替換掉父類型。(關于里氏替換原則的描述,Barbara Liskov女士的描述比這個要復雜得多,但簡單的說就是能用父類型的地方就一定能使用子類型。里氏替換原則可以檢查繼承關系是否合理,如果一個繼承關系違背了里氏替換原則,那么這個繼承關系一定是錯誤的,需要對代碼進行重構。例如讓貓繼承狗,或者狗繼承貓,又或者讓正方形繼承長方形都是錯誤的繼承關系,因為你很容易找到違反里氏替換原則的場景。需要注意的是:子類一定是增加父類的能力而不是減少父類的能力,因為子類比父類的能力更多,把能力多的對象當成能力少的對象來用當然沒有任何問題。)? - 接口隔離原則:接口要小而專,絕不能大而全。(臃腫的接口是對接口的污染,既然接口表示能力,那么一個接口只應該描述一種能力,接口也應該是高度內聚的。例如,琴棋書畫就應該分別設計為四個接口,而不應設計成一個接口中的四個方法,因為如果設計成一個接口中的四個方法,那么這個接口很難用,畢竟琴棋書畫四樣都精通的人還是少數,而如果設計成四個接口,會幾項就實現幾個接口,這樣的話每個接口被復用的可能性是很高的。Java中的接口代表能力、代表約定、代表角色,能否正確的使用接口一定是編程水平高低的重要標識。)? - 合成聚合復用原則:優先使用聚合或合成關系復用代碼。(通過繼承來復用代碼是面向對象程序設計中被濫用得最多的東西,因為所有的教科書都無一例外的對繼承進行了鼓吹從而誤導了初學者,類與類之間簡單的說有三種關系,Is-A關系、Has-A關系、Use-A關系,分別代表繼承、關聯和依賴。其中,關聯關系根據其關聯的強度又可以進一步劃分為關聯、聚合和合成,但說白了都是Has-A關系,合成聚合復用原則想表達的是優先考慮Has-A關系而不是Is-A關系復用代碼,原因嘛可以自己從百度上找到一萬個理由,需要說明的是,即使在Java的API中也有不少濫用繼承的例子,例如Properties類繼承了Hashtable類,Stack類繼承了Vector類,這些繼承明顯就是錯誤的,更好的做法是在Properties類中放置一個Hashtable類型的成員并且將其鍵和值都設置為字符串來存儲數據,而Stack類的設計也應該是在Stack類中放一個Vector對象來存儲數據。記住:任何時候都不要繼承工具類,工具是可以擁有并可以使用的,而不是拿來繼承的。)? - 迪米特法則:迪米特法則又叫最少知識原則,一個對象應當對其他對象有盡可能少的了解。(迪米特法則簡單的說就是如何做到"低耦合",門面模式和調停者模式就是對迪米特法則的踐行。對于門面模式可以舉一個簡單的例子,你去一家公司洽談業務,你不需要了解這個公司內部是如何運作的,你甚至可以對這個公司一無所知,去的時候只需要找到公司入口處的前臺美女,告訴她們你要做什么,她們會找到合適的人跟你接洽,前臺的美女就是公司這個系統的門面。再復雜的系統都可以為用戶提供一個簡單的門面,Java Web開發中作為前端控制器的Servlet或Filter不就是一個門面嗎,瀏覽器對服務器的運作方式一無所知,但是通過前端控制器就能夠根據你的請求得到相應的服務。調停者模式也可以舉一個簡單的例子來說明,例如一臺計算機,CPU、內存、硬盤、顯卡、聲卡各種設備需要相互配合才能很好的工作,但是如果這些東西都直接連接到一起,計算機的布線將異常復雜,在這種情況下,主板作為一個調停者的身份出現,它將各個設備連接在一起而不需要每個設備之間直接交換數據,這樣就減小了系統的耦合度和復雜度,如下圖所示。迪米特法則用通俗的話來將就是不要和陌生人打交道,如果真的需要,找一個自己的朋友,讓他替你和陌生人打交道。)?

? ?

90、簡述一下你了解的設計模式。? 答:所謂設計模式,就是一套被反復使用的代碼設計經驗的總結(情境中一個問題經過證實的一個解決方案)。使用設計模式是為了可重用代碼、讓代碼更容易被他人理解、保證代碼可靠性。設計模式使人們可以更加簡單方便的復用成功的設計和體系結構。將已證實的技術表述成設計模式也會使新系統開發者更加容易理解其設計思路。? 在GoF的《Design Patterns: Elements of Reusable Object-Oriented Software》中給出了三類(創建型[對類的實例化過程的抽象化]、結構型[描述如何將類或對象結合在一起形成更大的結構]、行為型[對在不同的對象之間劃分責任和算法的抽象化])共23種設計模式,包括:Abstract Factory(抽象工廠模式),Builder(建造者模式),Factory Method(工廠方法模式),Prototype(原始模型模式),Singleton(單例模式);Facade(門面模式),Adapter(適配器模式),Bridge(橋梁模式),Composite(合成模式),Decorator(裝飾模式),Flyweight(享元模式),Proxy(代理模式);Command(命令模式),Interpreter(解釋器模式),Visitor(訪問者模式),Iterator(迭代子模式),Mediator(調停者模式),Memento(備忘錄模式),Observer(觀察者模式),State(狀態模式),Strategy(策略模式),Template Method(模板方法模式), Chain Of Responsibility(責任鏈模式)。? 面試被問到關于設計模式的知識時,可以揀最常用的作答,例如:? - 工廠模式:工廠類可以根據條件生成不同的子類實例,這些子類有一個公共的抽象父類并且實現了相同的方法,但是這些方法針對不同的數據進行了不同的操作(多態方法)。當得到子類的實例后,開發人員可以調用基類中的方法而不必考慮到底返回的是哪一個子類的實例。? - 代理模式:給一個對象提供一個代理對象,并由代理對象控制原對象的引用。實際開發中,按照使用目的的不同,代理可以分為:遠程代理、虛擬代理、保護代理、Cache代理、防火墻代理、同步化代理、智能引用代理。? - 適配器模式:把一個類的接口變換成客戶端所期待的另一種接口,從而使原本因接口不匹配而無法在一起使用的類能夠一起工作。? - 模板方法模式:提供一個抽象類,將部分邏輯以具體方法或構造器的形式實現,然后聲明一些抽象方法來迫使子類實現剩余的邏輯。不同的子類可以以不同的方式實現這些抽象方法(多態實現),從而實現不同的業務邏輯。? 除此之外,還可以講講上面提到的門面模式、橋梁模式、單例模式、裝潢模式(Collections工具類和I/O系統中都使用裝潢模式)等,反正基本原則就是揀自己最熟悉的、用得最多的作答,以免言多必失。??

91、用Java寫一個單例類。? 答:? - 餓漢式單例?

public class Singleton {

? ? private Singleton(){}

? ? private static Singleton instance = new Singleton();

? ? public static Singleton getInstance(){

? ? ? ? return instance;

? ? }

}?

懶漢式單例?

public class Singleton {

? ? private static Singleton instance = null;

? ? private Singleton() {}

? ? public static synchronized Singleton getInstance(){

? ? ? ? if (instance == null) instance = new Singleton();

? ? ? ? return instance;

? ? }

}?

?

?注意:實現一個單例有兩點注意事項,①將構造器私有,不允許外界通過構造器創建對象;②通過公開的靜態方法向外界返回類的唯一實例。這里有一個問題可以思考:Spring的IoC容器可以為普通的類創建單例,它是怎么做到的呢??

?

92、什么是UML?? 答:UML是統一建模語言(Unified Modeling Language)的縮寫,它發表于1997年,綜合了當時已經存在的面向對象的建模語言、方法和過程,是一個支持模型化和軟件系統開發的圖形化語言,為軟件開發的所有階段提供模型化和可視化支持。使用UML可以幫助溝通與交流,輔助應用設計和文檔的生成,還能夠闡釋系統的結構和行為。?

93、UML中有哪些常用的圖?? 答:UML定義了多種圖形化的符號來描述軟件系統部分或全部的靜態結構和動態結構,包括:用例圖(use case diagram)、類圖(class diagram)、時序圖(sequence diagram)、協作圖(collaboration diagram)、狀態圖(statechart diagram)、活動圖(activity diagram)、構件圖(component diagram)、部署圖(deployment diagram)等。在這些圖形化符號中,有三種圖最為重要,分別是:用例圖(用來捕獲需求,描述系統的功能,通過該圖可以迅速的了解系統的功能模塊及其關系)、類圖(描述類以及類與類之間的關系,通過該圖可以快速了解系統)、時序圖(描述執行特定任務時對象之間的交互關系以及執行順序,通過該圖可以了解對象能接收的消息也就是說對象能夠向外界提供的服務)。? 用例圖:? ? 類圖:? ? 時序圖:? ?

94、用Java寫一個冒泡排序。? 答:冒泡排序幾乎是個程序員都寫得出來,但是面試的時候如何寫一個逼格高的冒泡排序卻不是每個人都能做到,下面提供一個參考代碼:?

import java.util.Comparator;

?

/**

?* 排序器接口(策略模式: 將算法封裝到具有共同接口的獨立的類中使得它們可以相互替換)

?* @author駱昊

?*

?*/

public interface Sorter {

?

? ?/**

? ? * 排序

? ? * @param list 待排序的數組

? ? */

? ?public <T extends Comparable<T>> void sort(T[] list);

?

? ?/**

? ? * 排序

? ? * @param list 待排序的數組

? ? * @param comp 比較兩個對象的比較器

? ? */

? ?public <T> void sort(T[] list, Comparator<T> comp);

}?

import java.util.Comparator;

?

/**

?* 冒泡排序

?*?

?* @author駱昊

?*

?*/

public class BubbleSorter implements Sorter {

?

? ? @Override

? ? public <T extends Comparable<T>> void sort(T[] list) {

? ? ? ? boolean swapped = true;

? ? ? ? for (int i = 1, len = list.length; i < len && swapped; ++i) {

? ? ? ? ? ? swapped = false;

? ? ? ? ? ? for (int j = 0; j < len - i; ++j) {

? ? ? ? ? ? ? ? if (list[j].compareTo(list[j + 1]) > 0) {

? ? ? ? ? ? ? ? ? ? T temp = list[j];

? ? ? ? ? ? ? ? ? ? list[j] = list[j + 1];

? ? ? ? ? ? ? ? ? ? list[j + 1] = temp;

? ? ? ? ? ? ? ? ? ? swapped = true;

? ? ? ? ? ? ? ? }

? ? ? ? ? ? }

? ? ? ? }

? ? }

?

? ? @Override

? ? public <T> void sort(T[] list, Comparator<T> comp) {

? ? ? ? boolean swapped = true;

? ? ? ? for (int i = 1, len = list.length; i < len && swapped; ++i) {

? ? ? ? ? ? swapped = false;

? ? ? ? ? ? for (int j = 0; j < len - i; ++j) {

? ? ? ? ? ? ? ? if (comp.compare(list[j], list[j + 1]) > 0) {

? ? ? ? ? ? ? ? ? ? T temp = list[j];

? ? ? ? ? ? ? ? ? ? list[j] = list[j + 1];

? ? ? ? ? ? ? ? ? ? list[j + 1] = temp;

? ? ? ? ? ? ? ? ? ? swapped = true;

? ? ? ? ? ? ? ? }

? ? ? ? ? ? }

? ? ? ? }

? ? }

}?

95、用Java寫一個折半查找。? 答:折半查找,也稱二分查找、二分搜索,是一種在有序數組中查找某一特定元素的搜索算法。搜素過程從數組的中間元素開始,如果中間元素正好是要查找的元素,則搜素過程結束;如果某一特定元素大于或者小于中間元素,則在數組大于或小于中間元素的那一半中查找,而且跟開始一樣從中間元素開始比較。如果在某一步驟數組已經為空,則表示找不到指定的元素。這種搜索算法每一次比較都使搜索范圍縮小一半,其時間復雜度是O(logN)。?

import java.util.Comparator;

?

public class MyUtil {

?

? ?public static <T extends Comparable<T>> int binarySearch(T[] x, T key) {

? ? ? return binarySearch(x, 0, x.length- 1, key);

? ?}

?

? ?// 使用循環實現的二分查找

? ?public static <T> int binarySearch(T[] x, T key, Comparator<T> comp) {

? ? ? int low = 0;

? ? ? int high = x.length - 1;

? ? ? while (low <= high) {

? ? ? ? ? int mid = (low + high) >>> 1;

? ? ? ? ? int cmp = comp.compare(x[mid], key);

? ? ? ? ? if (cmp < 0) {

? ? ? ? ? ? low= mid + 1;

? ? ? ? ? }

? ? ? ? ? else if (cmp > 0) {

? ? ? ? ? ? high= mid - 1;

? ? ? ? ? }

? ? ? ? ? else {

? ? ? ? ? ? return mid;

? ? ? ? ? }

? ? ? }

? ? ? return -1;

? ?}

?

? ?// 使用遞歸實現的二分查找

? ?private static<T extends Comparable<T>> int binarySearch(T[] x, int low, int high, T key) {

? ? ? if(low <= high) {

? ? ? ? int mid = low + ((high -low) >> 1);

? ? ? ? if(key.compareTo(x[mid])== 0) {

? ? ? ? ? ?return mid;

? ? ? ? }

? ? ? ? else if(key.compareTo(x[mid])< 0) {

? ? ? ? ? ?return binarySearch(x,low, mid - 1, key);

? ? ? ? }

? ? ? ? else {

? ? ? ? ? ?return binarySearch(x,mid + 1, high, key);

? ? ? ? }

? ? ? }

? ? ? return -1;

? ?}

}?

?

?說明:上面的代碼中給出了折半查找的兩個版本,一個用遞歸實現,一個用循環實現。需要注意的是計算中間位置時不應該使用(high+ low) / 2的方式,因為加法運算可能導致整數越界,這里應該使用以下三種方式之一:low + (high - low) / 2或low + (high – low) >> 1或(low + high) >>> 1(>>>是邏輯右移,是不帶符號位的右移)

總結

以上是生活随笔為你收集整理的[转载] Java面试题全集(上)的全部內容,希望文章能夠幫你解決所遇到的問題。

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

久久国产自偷自偷免费一区调 | 青青草原综合久久大伊人精品 | 亚洲人成网站免费播放 | 亚洲国产精品一区二区美利坚 | 国产成人无码a区在线观看视频app | 国产九九九九九九九a片 | 人人爽人人爽人人片av亚洲 | 中文无码成人免费视频在线观看 | 中文久久乱码一区二区 | 亚洲精品国产品国语在线观看 | 日本熟妇乱子伦xxxx | 国产乱人伦av在线无码 | 狠狠综合久久久久综合网 | 精品水蜜桃久久久久久久 | 欧美老人巨大xxxx做受 | 精品国产一区二区三区av 性色 | 国产精品资源一区二区 | 久精品国产欧美亚洲色aⅴ大片 | 国内精品九九久久久精品 | 亚洲va欧美va天堂v国产综合 | 精品久久久无码中文字幕 | 中文无码精品a∨在线观看不卡 | 曰韩少妇内射免费播放 | 免费看少妇作爱视频 | 亚洲国产一区二区三区在线观看 | 日本一卡二卡不卡视频查询 | 国产精品无码一区二区桃花视频 | www成人国产高清内射 | 九一九色国产 | 欧美丰满老熟妇xxxxx性 | 欧洲精品码一区二区三区免费看 | 欧美黑人巨大xxxxx | 欧美人与动性行为视频 | 一本无码人妻在中文字幕免费 | 亚洲精品国产品国语在线观看 | 18精品久久久无码午夜福利 | 国产av久久久久精东av | 国产sm调教视频在线观看 | 精品人人妻人人澡人人爽人人 | 精品国产av色一区二区深夜久久 | 国产无套粉嫩白浆在线 | 欧美怡红院免费全部视频 | 久久午夜夜伦鲁鲁片无码免费 | 秋霞特色aa大片 | 久久精品中文闷骚内射 | 国产无遮挡又黄又爽免费视频 | 在线观看免费人成视频 | 色噜噜亚洲男人的天堂 | 精品久久综合1区2区3区激情 | 日日橹狠狠爱欧美视频 | 日韩精品成人一区二区三区 | 波多野结衣一区二区三区av免费 | 国产精品久久精品三级 | www一区二区www免费 | 精品国偷自产在线 | 亚洲中文字幕无码中文字在线 | 婷婷丁香五月天综合东京热 | 少妇无码吹潮 | 色欲人妻aaaaaaa无码 | 国产成人精品久久亚洲高清不卡 | 永久免费精品精品永久-夜色 | 精品久久久中文字幕人妻 | 清纯唯美经典一区二区 | 国产激情综合五月久久 | 国产午夜无码精品免费看 | 麻豆av传媒蜜桃天美传媒 | 色妞www精品免费视频 | 天堂亚洲2017在线观看 | 国产精品第一区揄拍无码 | 免费无码肉片在线观看 | 国产成人亚洲综合无码 | 国产精品久久国产三级国 | 中文精品久久久久人妻不卡 | 久久精品国产大片免费观看 | 男女作爱免费网站 | 欧美日韩一区二区免费视频 | 俄罗斯老熟妇色xxxx | 亚洲国产欧美日韩精品一区二区三区 | 国产成人精品视频ⅴa片软件竹菊 | 午夜成人1000部免费视频 | 国产色视频一区二区三区 | 亚洲国产精品无码久久久久高潮 | 99久久人妻精品免费一区 | 亚洲精品一区二区三区四区五区 | 久久精品国产大片免费观看 | 老熟女重囗味hdxx69 | 亚洲中文字幕va福利 | 欧美 亚洲 国产 另类 | 国产亚洲美女精品久久久2020 | 亚洲成熟女人毛毛耸耸多 | 精品无码一区二区三区爱欲 | 成人无码精品1区2区3区免费看 | 国产免费观看黄av片 | 99久久99久久免费精品蜜桃 | 午夜精品一区二区三区在线观看 | 国产精品久久久久久无码 | 亚洲天堂2017无码 | 伊人久久大香线蕉亚洲 | 强奷人妻日本中文字幕 | 狠狠色噜噜狠狠狠7777奇米 | av无码不卡在线观看免费 | 精品一区二区三区无码免费视频 | 久久99国产综合精品 | 99国产欧美久久久精品 | 免费观看又污又黄的网站 | 国产乡下妇女做爰 | 日本肉体xxxx裸交 | 亚洲天堂2017无码 | 免费国产成人高清在线观看网站 | 亚洲国产精品久久人人爱 | 中文字幕乱妇无码av在线 | 欧美人与善在线com | 国产免费久久精品国产传媒 | 国产精品无码久久av | 中文字幕无码热在线视频 | 国产熟妇高潮叫床视频播放 | 国产无遮挡又黄又爽免费视频 | 精品国产福利一区二区 | 青草视频在线播放 | √天堂资源地址中文在线 | 国产精品美女久久久网av | 极品嫩模高潮叫床 | 九九在线中文字幕无码 | 成人无码影片精品久久久 | 亚洲国产精品美女久久久久 | 婷婷六月久久综合丁香 | 少女韩国电视剧在线观看完整 | 真人与拘做受免费视频 | 久久亚洲日韩精品一区二区三区 | 亚洲第一无码av无码专区 | aⅴ亚洲 日韩 色 图网站 播放 | 亚洲va中文字幕无码久久不卡 | 国产办公室秘书无码精品99 | 国产精品久久久久无码av色戒 | 色欲久久久天天天综合网精品 | 日韩精品无码一区二区中文字幕 | 99精品视频在线观看免费 | 曰本女人与公拘交酡免费视频 | 特黄特色大片免费播放器图片 | 波多野结衣乳巨码无在线观看 | 又紧又大又爽精品一区二区 | 麻豆精品国产精华精华液好用吗 | 999久久久国产精品消防器材 | 久久精品国产亚洲精品 | 女高中生第一次破苞av | 香港三级日本三级妇三级 | 中文字幕日产无线码一区 | 午夜性刺激在线视频免费 | 日本一卡2卡3卡4卡无卡免费网站 国产一区二区三区影院 | 久久久久久国产精品无码下载 | 狠狠亚洲超碰狼人久久 | 午夜精品久久久内射近拍高清 | 中文字幕 亚洲精品 第1页 | 狂野欧美性猛xxxx乱大交 | 色情久久久av熟女人妻网站 | 男女性色大片免费网站 | 无码福利日韩神码福利片 | 成人欧美一区二区三区黑人免费 | 久久99精品久久久久久 | 久久久久久亚洲精品a片成人 | 东京热无码av男人的天堂 | 精品久久综合1区2区3区激情 | 四虎影视成人永久免费观看视频 | 久久aⅴ免费观看 | 无码毛片视频一区二区本码 | 中文字幕av日韩精品一区二区 | 中文字幕av日韩精品一区二区 | av人摸人人人澡人人超碰下载 | 精品无码一区二区三区爱欲 | 2019nv天堂香蕉在线观看 | 国内精品人妻无码久久久影院蜜桃 | 久久成人a毛片免费观看网站 | 久久久精品欧美一区二区免费 | 夫妻免费无码v看片 | 日本xxxx色视频在线观看免费 | 色 综合 欧美 亚洲 国产 | 一个人看的视频www在线 | 国产做国产爱免费视频 | 精品国产一区二区三区四区在线看 | 四虎永久在线精品免费网址 | 亚洲中文无码av永久不收费 | 少女韩国电视剧在线观看完整 | ass日本丰满熟妇pics | 精品一区二区不卡无码av | 亚洲色无码一区二区三区 | 亚洲精品美女久久久久久久 | 色欲av亚洲一区无码少妇 | 55夜色66夜色国产精品视频 | 亚洲成a人一区二区三区 | 国产亚洲精品久久久久久大师 | 国产在热线精品视频 | 国内精品久久久久久中文字幕 | 亚洲精品成a人在线观看 | 美女黄网站人色视频免费国产 | 久久亚洲精品成人无码 | 伊在人天堂亚洲香蕉精品区 | 国产成人av免费观看 | 国产色在线 | 国产 | 久久国产精品二国产精品 | 麻豆成人精品国产免费 | 免费中文字幕日韩欧美 | 青青青爽视频在线观看 | 成人片黄网站色大片免费观看 | 免费观看的无遮挡av | 永久免费观看国产裸体美女 | 99久久人妻精品免费一区 | 一本久道久久综合婷婷五月 | 欧美一区二区三区视频在线观看 | 久久五月精品中文字幕 | 亚洲一区二区三区偷拍女厕 | 秋霞成人午夜鲁丝一区二区三区 | 荫蒂被男人添的好舒服爽免费视频 | 亚洲人成影院在线无码按摩店 | 国产网红无码精品视频 | 久久久久人妻一区精品色欧美 | 国产性猛交╳xxx乱大交 国产精品久久久久久无码 欧洲欧美人成视频在线 | 日韩精品一区二区av在线 | 蜜臀av无码人妻精品 | 欧美日韩视频无码一区二区三 | 国产精华av午夜在线观看 | 精品国产aⅴ无码一区二区 | 曰韩少妇内射免费播放 | 亚欧洲精品在线视频免费观看 | 成人性做爰aaa片免费看 | 久久精品视频在线看15 | 国产精品va在线观看无码 | 国产疯狂伦交大片 | www国产精品内射老师 | 国产精品人人爽人人做我的可爱 | 亚洲精品国偷拍自产在线观看蜜桃 | 激情亚洲一区国产精品 | 亚洲精品一区三区三区在线观看 | 国产乱子伦视频在线播放 | 极品嫩模高潮叫床 | 人人妻人人澡人人爽人人精品浪潮 | 国产成人综合色在线观看网站 | 国产无遮挡吃胸膜奶免费看 | 亚洲成a人片在线观看无码 | 日韩欧美中文字幕公布 | 三上悠亚人妻中文字幕在线 | 亚洲精品久久久久久一区二区 | 免费无码午夜福利片69 | 国产免费久久久久久无码 | 成人综合网亚洲伊人 | 亚洲色欲色欲欲www在线 | 日本www一道久久久免费榴莲 | 网友自拍区视频精品 | 国内精品人妻无码久久久影院 | 99久久人妻精品免费二区 | 亚洲国产高清在线观看视频 | 国精品人妻无码一区二区三区蜜柚 | 最近中文2019字幕第二页 | 欧美人与物videos另类 | 国产成人精品必看 | 日韩精品a片一区二区三区妖精 | 久久精品丝袜高跟鞋 | 狠狠色欧美亚洲狠狠色www | 中文字幕无码免费久久9一区9 | 蜜臀aⅴ国产精品久久久国产老师 | 无码人妻精品一区二区三区不卡 | 国产免费久久精品国产传媒 | 国产黄在线观看免费观看不卡 | 小鲜肉自慰网站xnxx | 精品一二三区久久aaa片 | 亚欧洲精品在线视频免费观看 | 中文字幕乱码中文乱码51精品 | 色婷婷欧美在线播放内射 | 欧美老妇与禽交 | 十八禁视频网站在线观看 | 精品成在人线av无码免费看 | 无码任你躁久久久久久久 | 图片区 小说区 区 亚洲五月 | 欧洲欧美人成视频在线 | 亚洲熟妇色xxxxx亚洲 | a在线亚洲男人的天堂 | 小鲜肉自慰网站xnxx | 精品无码一区二区三区爱欲 | 精品无人国产偷自产在线 | 少妇邻居内射在线 | 国产色视频一区二区三区 | 亚洲色大成网站www国产 | 精品久久8x国产免费观看 | 爽爽影院免费观看 | 成 人 网 站国产免费观看 | 亚洲熟悉妇女xxx妇女av | 永久免费精品精品永久-夜色 | 国产在线精品一区二区高清不卡 | 亚洲毛片av日韩av无码 | 中文字幕日韩精品一区二区三区 | 超碰97人人做人人爱少妇 | 少妇无码一区二区二三区 | 久久国语露脸国产精品电影 | 亚洲乱亚洲乱妇50p | 国产精品免费大片 | 国产明星裸体无码xxxx视频 | 国产精品久久国产三级国 | 国产香蕉97碰碰久久人人 | 人妻少妇精品视频专区 | 国产97在线 | 亚洲 | 国产精品欧美成人 | 日欧一片内射va在线影院 | 亚洲最大成人网站 | 成人欧美一区二区三区 | 中文字幕 亚洲精品 第1页 | 国产又爽又猛又粗的视频a片 | www一区二区www免费 | 成人精品视频一区二区 | 亚洲国产精品一区二区美利坚 | 人人妻人人澡人人爽人人精品 | 欧美日韩色另类综合 | 特级做a爰片毛片免费69 | 免费无码一区二区三区蜜桃大 | 国产亚洲人成a在线v网站 | 久久亚洲a片com人成 | 狠狠综合久久久久综合网 | 亚洲中文字幕无码一久久区 | av人摸人人人澡人人超碰下载 | 国产激情精品一区二区三区 | 国产热a欧美热a在线视频 | 男人扒开女人内裤强吻桶进去 | 2019nv天堂香蕉在线观看 | 无遮挡啪啪摇乳动态图 | 内射巨臀欧美在线视频 | 波多野结衣 黑人 | 国内少妇偷人精品视频 | 色一情一乱一伦 | 色噜噜亚洲男人的天堂 | 亚洲va欧美va天堂v国产综合 | 色一情一乱一伦一视频免费看 | 激情爆乳一区二区三区 | 网友自拍区视频精品 | 免费无码av一区二区 | 中文字幕无码热在线视频 | 国产成人精品一区二区在线小狼 | 国产人妻精品一区二区三区不卡 | 久久精品丝袜高跟鞋 | 亚洲中文字幕久久无码 | 噜噜噜亚洲色成人网站 | 中文字幕无线码免费人妻 | 午夜理论片yy44880影院 | 色情久久久av熟女人妻网站 | 国产综合久久久久鬼色 | 久久无码人妻影院 | 久久人人爽人人爽人人片ⅴ | 欧美xxxx黑人又粗又长 | 久久久国产一区二区三区 | 国产 精品 自在自线 | 亚洲精品综合一区二区三区在线 | 色综合久久久无码网中文 | 麻豆国产人妻欲求不满 | 国产三级久久久精品麻豆三级 | 中文字幕精品av一区二区五区 | 一区二区三区乱码在线 | 欧洲 | 大乳丰满人妻中文字幕日本 | 婷婷五月综合缴情在线视频 | 国产一区二区三区日韩精品 | 亚洲中文字幕av在天堂 | 男人的天堂2018无码 | 中文亚洲成a人片在线观看 | 国产免费久久精品国产传媒 | 又粗又大又硬毛片免费看 | 色综合久久久无码中文字幕 | 国语自产偷拍精品视频偷 | 久久久国产精品无码免费专区 | 国产精品对白交换视频 | 亚洲va中文字幕无码久久不卡 | 女人被爽到呻吟gif动态图视看 | 国产成人无码av一区二区 | 欧美人与禽zoz0性伦交 | 欧美亚洲国产一区二区三区 | 亚洲中文字幕无码中文字在线 | 欧美精品一区二区精品久久 | aⅴ亚洲 日韩 色 图网站 播放 | 国产成人精品无码播放 | 麻花豆传媒剧国产免费mv在线 | 精品亚洲成av人在线观看 | 国产情侣作爱视频免费观看 | 色婷婷久久一区二区三区麻豆 | 女人被爽到呻吟gif动态图视看 | 日日碰狠狠丁香久燥 | 精品少妇爆乳无码av无码专区 | 又紧又大又爽精品一区二区 | 强开小婷嫩苞又嫩又紧视频 | 人人爽人人澡人人高潮 | 波多野结衣乳巨码无在线观看 | 狠狠cao日日穞夜夜穞av | 亚洲精品午夜国产va久久成人 | 国产精品亚洲五月天高清 | 日本乱人伦片中文三区 | 又湿又紧又大又爽a视频国产 | 久久亚洲精品中文字幕无男同 | 亚洲乱码国产乱码精品精 | 草草网站影院白丝内射 | 亚洲毛片av日韩av无码 | 偷窥日本少妇撒尿chinese | 色婷婷欧美在线播放内射 | 国内精品一区二区三区不卡 | 久久99热只有频精品8 | 中文字幕 人妻熟女 | 超碰97人人做人人爱少妇 | 大肉大捧一进一出视频出来呀 | 国产亚洲tv在线观看 | 少妇人妻av毛片在线看 | 久久zyz资源站无码中文动漫 | 青草青草久热国产精品 | 亚洲精品午夜国产va久久成人 | 国产精品久久久久7777 | www国产亚洲精品久久久日本 | 精品亚洲韩国一区二区三区 | 成人一区二区免费视频 | 国产又爽又黄又刺激的视频 | 2020久久香蕉国产线看观看 | 久久精品女人天堂av免费观看 | 中文字幕日韩精品一区二区三区 | 欧美日韩一区二区免费视频 | 任你躁在线精品免费 | 亚洲中文字幕无码一久久区 | 成人精品视频一区二区三区尤物 | 国产性生交xxxxx无码 | 麻豆av传媒蜜桃天美传媒 | 欧美成人高清在线播放 | 夜夜躁日日躁狠狠久久av | 97夜夜澡人人爽人人喊中国片 | 国产无av码在线观看 | 亚洲成a人一区二区三区 | 日韩精品成人一区二区三区 | 国产精品国产自线拍免费软件 | 中文字幕无码av激情不卡 | 欧美日本精品一区二区三区 | 精品人妻中文字幕有码在线 | 日韩精品一区二区av在线 | 5858s亚洲色大成网站www | 精品国产精品久久一区免费式 | 国产无套内射久久久国产 | 狠狠色噜噜狠狠狠狠7777米奇 | 久久久精品人妻久久影视 | 国产97人人超碰caoprom | 欧美三级不卡在线观看 | 装睡被陌生人摸出水好爽 | 日韩精品乱码av一区二区 | 日日天干夜夜狠狠爱 | 日日天日日夜日日摸 | 男人扒开女人内裤强吻桶进去 | 丰满人妻被黑人猛烈进入 | 国产偷自视频区视频 | 久久亚洲中文字幕精品一区 | 免费中文字幕日韩欧美 | 亚洲综合无码一区二区三区 | 国产精品99久久精品爆乳 | 久久精品国产亚洲精品 | 久久久精品国产sm最大网站 | 少妇的肉体aa片免费 | 日产精品高潮呻吟av久久 | 十八禁真人啪啪免费网站 | 国产精品第一区揄拍无码 | 精品国精品国产自在久国产87 | 国产成人精品久久亚洲高清不卡 | 欧美性生交xxxxx久久久 | 日本一卡2卡3卡四卡精品网站 | 亚洲国产精品美女久久久久 | www国产精品内射老师 | 欧美野外疯狂做受xxxx高潮 | 最近的中文字幕在线看视频 | 亚洲乱码日产精品bd | 无码国产乱人伦偷精品视频 | 夜先锋av资源网站 | 国产精品无码久久av | 久久熟妇人妻午夜寂寞影院 | 欧美性色19p | 久久久久久国产精品无码下载 | 日本在线高清不卡免费播放 | 国产av剧情md精品麻豆 | 成人免费无码大片a毛片 | 成熟妇人a片免费看网站 | 久久精品国产99精品亚洲 | 精品久久久中文字幕人妻 | 无码一区二区三区在线 | 日韩人妻无码一区二区三区久久99 | 亚洲国产精华液网站w | 中文字幕+乱码+中文字幕一区 | 国产av人人夜夜澡人人爽麻豆 | 正在播放老肥熟妇露脸 | 国产一精品一av一免费 | 精品无人区无码乱码毛片国产 | 亚洲第一网站男人都懂 | 日欧一片内射va在线影院 | 99精品视频在线观看免费 | 亚洲综合无码一区二区三区 | 午夜无码区在线观看 | 久久久久人妻一区精品色欧美 | 一本色道久久综合狠狠躁 | 好男人www社区 | 中文字幕亚洲情99在线 | 无码国模国产在线观看 | 国产乱人伦app精品久久 国产在线无码精品电影网 国产国产精品人在线视 | 国产成人精品视频ⅴa片软件竹菊 | 2019午夜福利不卡片在线 | 波多野结衣高清一区二区三区 | 狂野欧美激情性xxxx | 天天摸天天透天天添 | 亚洲热妇无码av在线播放 | 曰韩无码二三区中文字幕 | 粗大的内捧猛烈进出视频 | 亚洲国产精品无码久久久久高潮 | 蜜桃视频插满18在线观看 | 久久亚洲精品中文字幕无男同 | 日韩精品一区二区av在线 | 国产精品嫩草久久久久 | 亚洲色成人中文字幕网站 | 亚洲精品综合五月久久小说 | 天堂无码人妻精品一区二区三区 | 亚洲 a v无 码免 费 成 人 a v | 免费看男女做好爽好硬视频 | 无码午夜成人1000部免费视频 | 中文字幕无码av波多野吉衣 | 性欧美大战久久久久久久 | 妺妺窝人体色www婷婷 | 内射后入在线观看一区 | 性色欲网站人妻丰满中文久久不卡 | 欧美野外疯狂做受xxxx高潮 | 蜜臀aⅴ国产精品久久久国产老师 | 蜜臀av无码人妻精品 | 亚洲精品中文字幕乱码 | 精品午夜福利在线观看 | 午夜性刺激在线视频免费 | 无码人妻精品一区二区三区下载 | 婷婷丁香五月天综合东京热 | 国产九九九九九九九a片 | 福利一区二区三区视频在线观看 | 欧美35页视频在线观看 | 成人免费视频一区二区 | 三级4级全黄60分钟 | 精品国产青草久久久久福利 | 亚洲综合在线一区二区三区 | 国产精品多人p群无码 | 亚洲啪av永久无码精品放毛片 | 影音先锋中文字幕无码 | 男女下面进入的视频免费午夜 | 精品国产av色一区二区深夜久久 | 高清国产亚洲精品自在久久 | 色综合天天综合狠狠爱 | 澳门永久av免费网站 | 欧美自拍另类欧美综合图片区 | 久久人人爽人人爽人人片ⅴ | 综合人妻久久一区二区精品 | 久久午夜无码鲁丝片午夜精品 | 狠狠色欧美亚洲狠狠色www | 国产农村乱对白刺激视频 | 精品水蜜桃久久久久久久 | 亚洲日本va中文字幕 | 亚洲性无码av中文字幕 | 成熟人妻av无码专区 | 亚洲精品国偷拍自产在线观看蜜桃 | 永久免费观看美女裸体的网站 | 久久午夜无码鲁丝片午夜精品 | 性啪啪chinese东北女人 | 国产激情一区二区三区 | 国产莉萝无码av在线播放 | 老子影院午夜精品无码 | 欧美国产亚洲日韩在线二区 | yw尤物av无码国产在线观看 | 国产乱人伦av在线无码 | 亚洲成a人片在线观看无码 | 牲交欧美兽交欧美 | 国产色精品久久人妻 | 又大又硬又黄的免费视频 | 亚洲精品中文字幕乱码 | 欧美激情一区二区三区成人 | 亚洲а∨天堂久久精品2021 | 九月婷婷人人澡人人添人人爽 | 午夜丰满少妇性开放视频 | 国产亚洲精品久久久久久大师 | 国产凸凹视频一区二区 | 久久精品中文字幕大胸 | 久久99热只有频精品8 | 国产亚洲tv在线观看 | 精品国产一区二区三区四区在线看 | 亚洲色偷偷男人的天堂 | 国产农村妇女高潮大叫 | 国产午夜无码视频在线观看 | 亚洲欧美国产精品久久 | 人妻少妇被猛烈进入中文字幕 | 兔费看少妇性l交大片免费 | 图片区 小说区 区 亚洲五月 | 偷窥日本少妇撒尿chinese | 欧美日韩一区二区综合 | 思思久久99热只有频精品66 | 日韩欧美中文字幕在线三区 | 成熟女人特级毛片www免费 | 日日摸日日碰夜夜爽av | 国内揄拍国内精品人妻 | 国产精品无码一区二区三区不卡 | 亚洲色欲色欲欲www在线 | 老太婆性杂交欧美肥老太 | 亚洲色大成网站www | 97色伦图片97综合影院 | 亚洲国产精品一区二区第一页 | 日本熟妇浓毛 | 无码人妻精品一区二区三区下载 | 天天拍夜夜添久久精品大 | 欧美丰满少妇xxxx性 | 国产内射老熟女aaaa | 水蜜桃色314在线观看 | 国产精品久久久午夜夜伦鲁鲁 | 久久99精品国产麻豆蜜芽 | 欧美日本精品一区二区三区 | 爆乳一区二区三区无码 | 日韩av无码一区二区三区不卡 | 国产午夜视频在线观看 | 国产色视频一区二区三区 | 人妻中文无码久热丝袜 | 亚洲国产成人a精品不卡在线 | 国产麻豆精品一区二区三区v视界 | 亚洲中文字幕无码一久久区 | 国产精品亚洲lv粉色 | 精品欧美一区二区三区久久久 | 亚洲成a人片在线观看无码3d | 国语自产偷拍精品视频偷 | 樱花草在线社区www | 无人区乱码一区二区三区 | 国产精品爱久久久久久久 | 十八禁视频网站在线观看 | 噜噜噜亚洲色成人网站 | 日韩av激情在线观看 | 国产明星裸体无码xxxx视频 | √8天堂资源地址中文在线 | 亚洲自偷精品视频自拍 | 99久久精品午夜一区二区 | 日韩 欧美 动漫 国产 制服 | 亚洲精品国产精品乱码视色 | 奇米影视7777久久精品 | 国产精品亚洲综合色区韩国 | 成人试看120秒体验区 | 久久久久成人精品免费播放动漫 | 国产亚洲tv在线观看 | 色欲人妻aaaaaaa无码 | 亚洲一区二区三区无码久久 | 国产精品沙发午睡系列 | 日韩亚洲欧美中文高清在线 | 精品日本一区二区三区在线观看 | 欧美 日韩 人妻 高清 中文 | 狠狠cao日日穞夜夜穞av | 一区二区三区乱码在线 | 欧洲 | 国内精品久久毛片一区二区 | 无码人妻丰满熟妇区五十路百度 | 日韩亚洲欧美中文高清在线 | 亚洲爆乳无码专区 | 欧美自拍另类欧美综合图片区 | 丰满妇女强制高潮18xxxx | 国产内射老熟女aaaa | 久热国产vs视频在线观看 | 国产精品18久久久久久麻辣 | 国产午夜亚洲精品不卡下载 | 国产真人无遮挡作爱免费视频 | 性欧美牲交在线视频 | 亚洲综合久久一区二区 | 粗大的内捧猛烈进出视频 | 无码人妻丰满熟妇区五十路百度 | 少妇人妻大乳在线视频 | 久久精品国产日本波多野结衣 | 人妻少妇精品视频专区 | 老子影院午夜伦不卡 | 亚洲 日韩 欧美 成人 在线观看 | 婷婷综合久久中文字幕蜜桃三电影 | 国产精品无码成人午夜电影 | 国产亚洲视频中文字幕97精品 | 久久午夜无码鲁丝片 | 又湿又紧又大又爽a视频国产 | 丰满少妇人妻久久久久久 | 国产成人无码a区在线观看视频app | 无码国产色欲xxxxx视频 | 亚洲人亚洲人成电影网站色 | 丝袜 中出 制服 人妻 美腿 | 国产一区二区三区日韩精品 | 两性色午夜免费视频 | 无码播放一区二区三区 | 国产偷抇久久精品a片69 | www国产亚洲精品久久网站 | 欧美35页视频在线观看 | 骚片av蜜桃精品一区 | 国产精品亚洲а∨无码播放麻豆 | 人妻少妇精品无码专区二区 | 麻豆国产人妻欲求不满 | 狠狠色丁香久久婷婷综合五月 | 久久久久久亚洲精品a片成人 | 国产成人无码专区 | 国产亚洲欧美日韩亚洲中文色 | 人妻插b视频一区二区三区 | 亚洲а∨天堂久久精品2021 | 久青草影院在线观看国产 | 欧美日韩色另类综合 | 欧美真人作爱免费视频 | 永久免费观看美女裸体的网站 | 99精品无人区乱码1区2区3区 | 偷窥日本少妇撒尿chinese | 亚洲自偷自拍另类第1页 | 国产在线精品一区二区三区直播 | 日韩视频 中文字幕 视频一区 | 午夜精品一区二区三区在线观看 | 日本又色又爽又黄的a片18禁 | 漂亮人妻洗澡被公强 日日躁 | 一本久久a久久精品亚洲 | 国产欧美精品一区二区三区 | 国产在线aaa片一区二区99 | 人人超人人超碰超国产 | 夜先锋av资源网站 | 国产精品久久久久9999小说 | 日本乱人伦片中文三区 | 熟女体下毛毛黑森林 | 久久亚洲a片com人成 | 成人三级无码视频在线观看 | 激情亚洲一区国产精品 | 亚洲精品一区三区三区在线观看 | 久精品国产欧美亚洲色aⅴ大片 | 久久精品中文字幕一区 | 麻豆成人精品国产免费 | 免费乱码人妻系列无码专区 | 中文字幕 人妻熟女 | 国产片av国语在线观看 | 成人欧美一区二区三区黑人 | 成 人影片 免费观看 | 国内精品久久久久久中文字幕 | 人人妻人人澡人人爽欧美一区 | 精品国产国产综合精品 | 中文字幕无码乱人伦 | 国产人妻精品一区二区三区不卡 | 国产内射爽爽大片视频社区在线 | 97se亚洲精品一区 | 国产办公室秘书无码精品99 | 国产麻豆精品精东影业av网站 | 亚洲国产精品美女久久久久 | 亚洲日韩一区二区三区 | 久久伊人色av天堂九九小黄鸭 | 国产精品鲁鲁鲁 | 2020久久香蕉国产线看观看 | 国产9 9在线 | 中文 | 最近的中文字幕在线看视频 | 欧美性生交活xxxxxdddd | 亚洲国精产品一二二线 | 国产超碰人人爽人人做人人添 | 久久久久99精品国产片 | 巨爆乳无码视频在线观看 | 国产午夜精品一区二区三区嫩草 | 久久久中文字幕日本无吗 | 欧美大屁股xxxxhd黑色 | 久久精品中文字幕一区 | 日本护士xxxxhd少妇 | 性欧美牲交xxxxx视频 | 日韩人妻无码中文字幕视频 | 日本肉体xxxx裸交 | 久久综合香蕉国产蜜臀av | 亚洲男人av天堂午夜在 | 日本熟妇人妻xxxxx人hd | 偷窥村妇洗澡毛毛多 | 精品久久综合1区2区3区激情 | 日韩人妻无码中文字幕视频 | 久久综合香蕉国产蜜臀av | 亚洲狠狠色丁香婷婷综合 | 国产午夜无码精品免费看 | 97久久精品无码一区二区 | 亚洲中文字幕在线无码一区二区 | 国产黄在线观看免费观看不卡 | 亚洲伊人久久精品影院 | 内射欧美老妇wbb | 欧美freesex黑人又粗又大 | 午夜免费福利小电影 | 精品无码av一区二区三区 | 久热国产vs视频在线观看 | 日日噜噜噜噜夜夜爽亚洲精品 | 国产精品久久国产三级国 | 无码人妻精品一区二区三区不卡 | 精品无码国产一区二区三区av | 国产精品99久久精品爆乳 | 超碰97人人做人人爱少妇 | 国产性生大片免费观看性 | 丰满护士巨好爽好大乳 | 亚洲色www成人永久网址 | 波多野结衣乳巨码无在线观看 | 中文字幕无码av波多野吉衣 | 亚洲日韩一区二区三区 | 日韩少妇内射免费播放 | 亚洲男人av天堂午夜在 | 中文字幕 亚洲精品 第1页 | 亚洲自偷自拍另类第1页 | 天堂一区人妻无码 | 97夜夜澡人人爽人人喊中国片 | 欧美黑人性暴力猛交喷水 | 亚洲阿v天堂在线 | 亚洲а∨天堂久久精品2021 | 欧美人妻一区二区三区 | 成人性做爰aaa片免费看 | 任你躁国产自任一区二区三区 | 亚洲精品无码国产 | 国产手机在线αⅴ片无码观看 | 国产免费久久久久久无码 | 国产97在线 | 亚洲 | 亚洲精品久久久久avwww潮水 | 欧美兽交xxxx×视频 | 婷婷五月综合激情中文字幕 | 久久综合给合久久狠狠狠97色 | 18无码粉嫩小泬无套在线观看 | 极品尤物被啪到呻吟喷水 | 青青草原综合久久大伊人精品 | 国产成人无码一二三区视频 | 久久zyz资源站无码中文动漫 | 精品无码国产自产拍在线观看蜜 | 好男人www社区 | 国产精品国产三级国产专播 | 日韩亚洲欧美中文高清在线 | 麻豆国产丝袜白领秘书在线观看 | 四十如虎的丰满熟妇啪啪 | 国精品人妻无码一区二区三区蜜柚 | 精品国精品国产自在久国产87 | 国产成人精品一区二区在线小狼 | 成人免费视频一区二区 | 精品无码一区二区三区爱欲 | 荫蒂被男人添的好舒服爽免费视频 | 性欧美熟妇videofreesex | 国产莉萝无码av在线播放 | 欧美xxxx黑人又粗又长 | 亚洲欧洲中文日韩av乱码 | 国产超碰人人爽人人做人人添 | 国产精品人妻一区二区三区四 | 久久久精品人妻久久影视 | 亚洲成a人一区二区三区 | 少妇无码一区二区二三区 | 亚洲一区av无码专区在线观看 | 国产精品99爱免费视频 | 亚洲国产精品美女久久久久 | 少妇人妻av毛片在线看 | 麻豆蜜桃av蜜臀av色欲av | 国产乱人伦av在线无码 | 又湿又紧又大又爽a视频国产 | 国产黑色丝袜在线播放 | 欧美xxxxx精品 | 免费看男女做好爽好硬视频 | 超碰97人人做人人爱少妇 | 国精品人妻无码一区二区三区蜜柚 | 国精品人妻无码一区二区三区蜜柚 | 无码av中文字幕免费放 | 亚洲精品国偷拍自产在线观看蜜桃 | 99久久99久久免费精品蜜桃 | 天天拍夜夜添久久精品 | 国精产品一区二区三区 | 天堂亚洲免费视频 | 亚洲精品国偷拍自产在线麻豆 | 18黄暴禁片在线观看 | 亚洲国产精品一区二区美利坚 | 国产精品久久久久无码av色戒 | av人摸人人人澡人人超碰下载 | 又粗又大又硬又长又爽 | 性做久久久久久久久 | 2020久久超碰国产精品最新 | 丰满肥臀大屁股熟妇激情视频 | 久热国产vs视频在线观看 | 国产精品亚洲专区无码不卡 | 最新国产乱人伦偷精品免费网站 | 18黄暴禁片在线观看 | 男女超爽视频免费播放 | 久久亚洲中文字幕精品一区 | 麻豆国产人妻欲求不满谁演的 | 高潮毛片无遮挡高清免费视频 | 老头边吃奶边弄进去呻吟 | 丰满人妻被黑人猛烈进入 | 国产熟女一区二区三区四区五区 | 欧美一区二区三区 | 色婷婷综合激情综在线播放 | 97久久超碰中文字幕 | 欧美性黑人极品hd | 国产成人综合色在线观看网站 | 国产成人精品三级麻豆 | 丰满人妻一区二区三区免费视频 | 色欲人妻aaaaaaa无码 | 欧美人与禽猛交狂配 | 国产美女极度色诱视频www | 成人免费视频在线观看 | 欧美一区二区三区视频在线观看 | 色狠狠av一区二区三区 | 18禁止看的免费污网站 | 少妇高潮喷潮久久久影院 | 欧美老人巨大xxxx做受 | 又大又硬又爽免费视频 | 国产精品无码成人午夜电影 | 日韩人妻无码一区二区三区久久99 | 搡女人真爽免费视频大全 | 粗大的内捧猛烈进出视频 | 天堂久久天堂av色综合 | 久久久久亚洲精品男人的天堂 | 久久久中文久久久无码 | 亚洲色无码一区二区三区 | 色欲人妻aaaaaaa无码 | 天天做天天爱天天爽综合网 | 中文无码精品a∨在线观看不卡 | 一区二区三区高清视频一 | 亚洲狠狠色丁香婷婷综合 | 国产无遮挡又黄又爽免费视频 | 一二三四社区在线中文视频 | 在线视频网站www色 | 色老头在线一区二区三区 | 又湿又紧又大又爽a视频国产 | 欧美第一黄网免费网站 | 国产人妻大战黑人第1集 | 亚洲 另类 在线 欧美 制服 | 亚洲中文字幕在线无码一区二区 | 国产免费无码一区二区视频 | 国产三级久久久精品麻豆三级 | 人妻少妇精品无码专区二区 | 亚洲人成人无码网www国产 | av人摸人人人澡人人超碰下载 | 亚洲国产精品无码久久久久高潮 | 日本丰满护士爆乳xxxx | 欧美大屁股xxxxhd黑色 | av人摸人人人澡人人超碰下载 | 乱中年女人伦av三区 | 欧美国产亚洲日韩在线二区 | 成人亚洲精品久久久久软件 | 精品午夜福利在线观看 | 国产精品久久国产精品99 | 东北女人啪啪对白 | 色爱情人网站 | 日本一卡2卡3卡4卡无卡免费网站 国产一区二区三区影院 | 久久国产36精品色熟妇 | 九九久久精品国产免费看小说 | 免费无码一区二区三区蜜桃大 | 成人毛片一区二区 | 欧美老人巨大xxxx做受 | 麻豆果冻传媒2021精品传媒一区下载 | 国产亚洲欧美日韩亚洲中文色 | 亚洲午夜无码久久 | 牲欲强的熟妇农村老妇女 | 东京无码熟妇人妻av在线网址 | 人妻少妇精品视频专区 | av无码久久久久不卡免费网站 | 乌克兰少妇性做爰 | 妺妺窝人体色www在线小说 | 中文字幕久久久久人妻 | 精品无码国产自产拍在线观看蜜 | www成人国产高清内射 | 久久精品99久久香蕉国产色戒 | 国产成人无码a区在线观看视频app | 动漫av网站免费观看 | 日本护士毛茸茸高潮 | 久久亚洲中文字幕精品一区 | v一区无码内射国产 | 午夜无码人妻av大片色欲 | 亚洲国产欧美国产综合一区 | 久久99久久99精品中文字幕 | 青青青手机频在线观看 | 亚洲精品一区二区三区大桥未久 | 亚洲国产欧美日韩精品一区二区三区 | 精品国产一区二区三区av 性色 | 无码av最新清无码专区吞精 | 亚洲色欲久久久综合网东京热 | 日本精品高清一区二区 | 97夜夜澡人人爽人人喊中国片 | 欧美国产亚洲日韩在线二区 | 野狼第一精品社区 | 免费人成在线观看网站 | 国产在线精品一区二区高清不卡 | 成人免费视频视频在线观看 免费 | 台湾无码一区二区 | 国内精品一区二区三区不卡 | 亚洲中文无码av永久不收费 | 久久精品中文字幕一区 | 3d动漫精品啪啪一区二区中 | 免费人成在线视频无码 | 成人免费无码大片a毛片 | 午夜成人1000部免费视频 | 久久久久亚洲精品男人的天堂 | 亚洲熟悉妇女xxx妇女av | 亚洲а∨天堂久久精品2021 | 欧美三级不卡在线观看 | 日本精品少妇一区二区三区 | 亚洲欧洲无卡二区视頻 | 国产无遮挡吃胸膜奶免费看 | 亚洲gv猛男gv无码男同 | 黑人巨大精品欧美黑寡妇 | 中文字幕无码免费久久9一区9 | 国产精品免费大片 | 国产国语老龄妇女a片 | 国产精品资源一区二区 | 国产香蕉尹人综合在线观看 | 日本一卡2卡3卡4卡无卡免费网站 国产一区二区三区影院 | 老熟妇乱子伦牲交视频 | 秋霞成人午夜鲁丝一区二区三区 | 国产舌乚八伦偷品w中 | 亚洲成a人片在线观看日本 | 永久免费观看美女裸体的网站 | 久久精品国产大片免费观看 | 欧美精品无码一区二区三区 | 精品国产一区二区三区四区 | 麻豆国产人妻欲求不满谁演的 | 中文字幕av伊人av无码av | 夜夜高潮次次欢爽av女 | 亚洲国产欧美日韩精品一区二区三区 | 亚洲成a人片在线观看日本 | 久久精品无码一区二区三区 | 俄罗斯老熟妇色xxxx | 精品国产麻豆免费人成网站 | 成 人 网 站国产免费观看 | 兔费看少妇性l交大片免费 | 天堂一区人妻无码 | 99久久久无码国产aaa精品 | 国产精品丝袜黑色高跟鞋 | 亚洲精品一区二区三区四区五区 | 国产亚洲精品久久久久久 | 亚洲精品久久久久久一区二区 | 久久天天躁狠狠躁夜夜免费观看 | 青青久在线视频免费观看 | 免费看少妇作爱视频 | 欧美国产日韩亚洲中文 | 欧美成人高清在线播放 | 最近的中文字幕在线看视频 | 人妻与老人中文字幕 | 成人免费视频一区二区 | 少妇久久久久久人妻无码 | 天天爽夜夜爽夜夜爽 | 久热国产vs视频在线观看 | 日韩亚洲欧美中文高清在线 | 国产精品国产三级国产专播 | 国产成人综合在线女婷五月99播放 | 日韩视频 中文字幕 视频一区 | 麻豆人妻少妇精品无码专区 | 人妻无码αv中文字幕久久琪琪布 | 日本大香伊一区二区三区 | 国内精品久久毛片一区二区 | 亚洲色在线无码国产精品不卡 | 国产亚洲欧美日韩亚洲中文色 | 亚洲精品中文字幕久久久久 | 亚洲男女内射在线播放 | 无码人妻黑人中文字幕 | 久9re热视频这里只有精品 | 日韩精品久久久肉伦网站 | 国产精品久久久久久亚洲影视内衣 | 奇米影视888欧美在线观看 | 中文字幕无码热在线视频 | 又粗又大又硬毛片免费看 | 狠狠亚洲超碰狼人久久 | 国产极品美女高潮无套在线观看 | 激情内射亚州一区二区三区爱妻 | 亚洲人成影院在线观看 | 美女黄网站人色视频免费国产 | 水蜜桃亚洲一二三四在线 | 大肉大捧一进一出视频出来呀 | 中文字幕av日韩精品一区二区 | 国产黑色丝袜在线播放 | 亚洲国产欧美国产综合一区 | 午夜精品久久久久久久 | 亚洲成a人片在线观看无码3d | 国产 精品 自在自线 | 色婷婷综合激情综在线播放 | 无码精品人妻一区二区三区av | 欧美人与禽zoz0性伦交 | 国产区女主播在线观看 | 国产成人综合美国十次 | 无码精品人妻一区二区三区av | 九九综合va免费看 | 东京一本一道一二三区 | 天堂а√在线地址中文在线 | 精品久久久久久人妻无码中文字幕 | 东京无码熟妇人妻av在线网址 | 亚洲一区二区三区在线观看网站 | 亚洲国产欧美日韩精品一区二区三区 | 亚洲欧美日韩综合久久久 | 熟妇女人妻丰满少妇中文字幕 | 动漫av网站免费观看 | 99久久人妻精品免费一区 | 日韩人妻系列无码专区 | 无码精品人妻一区二区三区av | 荫蒂被男人添的好舒服爽免费视频 | 大胆欧美熟妇xx | 国产av无码专区亚洲awww | 国产精品第一区揄拍无码 | 久久久久久a亚洲欧洲av冫 | 精品久久8x国产免费观看 | 精品国产国产综合精品 | 无码人妻精品一区二区三区下载 | 欧美人与物videos另类 | 人人澡人人透人人爽 | 任你躁国产自任一区二区三区 | 国产精品亚洲一区二区三区喷水 | 亚洲精品成a人在线观看 | 久久精品成人欧美大片 | 永久免费观看国产裸体美女 | 欧美人与善在线com | 成人av无码一区二区三区 | 中文字幕乱妇无码av在线 | 亚洲精品一区二区三区在线观看 | 国产精品福利视频导航 | 国产亚洲精品久久久ai换 | 无码播放一区二区三区 | 国产成人一区二区三区别 | 色综合久久久无码中文字幕 | 亚洲毛片av日韩av无码 | 日本精品人妻无码免费大全 | 麻豆果冻传媒2021精品传媒一区下载 | 亚洲色无码一区二区三区 | 日本乱偷人妻中文字幕 | 永久免费观看美女裸体的网站 | 激情综合激情五月俺也去 | 亚洲国产精品美女久久久久 | 啦啦啦www在线观看免费视频 | 中文字幕av无码一区二区三区电影 | 又黄又爽又色的视频 | 久久精品国产99精品亚洲 | 亚洲精品久久久久avwww潮水 | 日韩亚洲欧美中文高清在线 | 丰满人妻被黑人猛烈进入 | 乌克兰少妇xxxx做受 | 99国产欧美久久久精品 | 亚洲精品一区国产 | 精品无码一区二区三区的天堂 | 国产色在线 | 国产 | 婷婷丁香六月激情综合啪 | 88国产精品欧美一区二区三区 | 日本乱人伦片中文三区 | 欧美人妻一区二区三区 | 理论片87福利理论电影 | 两性色午夜视频免费播放 | 国产莉萝无码av在线播放 | 少妇无码av无码专区在线观看 | 国内精品人妻无码久久久影院蜜桃 | 极品嫩模高潮叫床 | 亚洲aⅴ无码成人网站国产app | 日日噜噜噜噜夜夜爽亚洲精品 | 亚洲aⅴ无码成人网站国产app | 久久午夜夜伦鲁鲁片无码免费 | 2020久久香蕉国产线看观看 | 国内综合精品午夜久久资源 | 丝袜足控一区二区三区 | 丰满岳乱妇在线观看中字无码 | 亚洲一区二区三区在线观看网站 | 欧美日韩视频无码一区二区三 | 女人被爽到呻吟gif动态图视看 | 亚洲人成网站在线播放942 | 亚洲经典千人经典日产 | 日本丰满熟妇videos | 日韩精品无码一本二本三本色 | 日产国产精品亚洲系列 | 亚洲综合另类小说色区 | 亚洲中文字幕在线观看 | 欧美亚洲日韩国产人成在线播放 | 亚洲无人区午夜福利码高清完整版 | 亚洲综合色区中文字幕 | 免费网站看v片在线18禁无码 | 午夜无码人妻av大片色欲 | 精品国产成人一区二区三区 | 乱人伦中文视频在线观看 | 久久人人爽人人爽人人片ⅴ | 免费乱码人妻系列无码专区 | 永久黄网站色视频免费直播 | 成人无码视频在线观看网站 | 欧美人与善在线com | 三级4级全黄60分钟 | 国产熟妇另类久久久久 | 西西人体www44rt大胆高清 | 男女爱爱好爽视频免费看 | 欧美色就是色 | 日韩欧美群交p片內射中文 | 国产精品丝袜黑色高跟鞋 | 欧美zoozzooz性欧美 | 成熟妇人a片免费看网站 | 精品国产一区二区三区四区 | 亚洲中文字幕无码一久久区 | 精品午夜福利在线观看 | 在线观看国产一区二区三区 | 国产人妻精品一区二区三区 | 久久久av男人的天堂 | 国产麻豆精品精东影业av网站 | 久久综合香蕉国产蜜臀av | 国产一区二区三区影院 | 精品成在人线av无码免费看 | 国内精品人妻无码久久久影院蜜桃 | 未满小14洗澡无码视频网站 | 麻花豆传媒剧国产免费mv在线 | 黑人巨大精品欧美一区二区 | 高中生自慰www网站 | 性色欲情网站iwww九文堂 | 国产色精品久久人妻 | 人人妻人人澡人人爽人人精品浪潮 | 亚洲性无码av中文字幕 | 日韩精品a片一区二区三区妖精 | 97资源共享在线视频 | 国产在热线精品视频 | 久久熟妇人妻午夜寂寞影院 | 国产手机在线αⅴ片无码观看 | 久久久久久久女国产乱让韩 | 国产精品久久福利网站 | 国产亚洲tv在线观看 | 波多野结衣av一区二区全免费观看 | 欧美日本精品一区二区三区 | 久久五月精品中文字幕 | 中文无码精品a∨在线观看不卡 | 免费无码的av片在线观看 | 欧洲vodafone精品性 | 欧美大屁股xxxxhd黑色 | 欧美 日韩 人妻 高清 中文 | 国产免费久久精品国产传媒 | 清纯唯美经典一区二区 | 99久久婷婷国产综合精品青草免费 | 欧美高清在线精品一区 | 国产激情精品一区二区三区 | 国产激情综合五月久久 | 正在播放老肥熟妇露脸 | 51国偷自产一区二区三区 | 波多野结衣乳巨码无在线观看 | 国产精品久免费的黄网站 | 久久99精品国产.久久久久 | 精品人妻人人做人人爽夜夜爽 | 无套内谢的新婚少妇国语播放 | аⅴ资源天堂资源库在线 | 特黄特色大片免费播放器图片 | 狠狠综合久久久久综合网 | 精品国产国产综合精品 | 国产三级精品三级男人的天堂 | 欧美日韩一区二区综合 | 麻豆国产人妻欲求不满谁演的 | 国产精品久久久久7777 | 奇米影视888欧美在线观看 | 午夜丰满少妇性开放视频 | 亚洲国产午夜精品理论片 | 国产精品久久久久影院嫩草 | 国产精品美女久久久久av爽李琼 | 久久亚洲中文字幕无码 | 久久亚洲精品中文字幕无男同 | 国产精品二区一区二区aⅴ污介绍 | 欧美丰满熟妇xxxx性ppx人交 | 少妇邻居内射在线 | 99久久精品日本一区二区免费 | 国产精品爱久久久久久久 | 国产精品亚洲综合色区韩国 | 精品国产成人一区二区三区 | 国产婷婷色一区二区三区在线 | 国精品人妻无码一区二区三区蜜柚 | 国产精品毛片一区二区 | 国产一区二区三区日韩精品 | 色综合久久久无码中文字幕 | а天堂中文在线官网 | 免费中文字幕日韩欧美 | 久久精品视频在线看15 | 特大黑人娇小亚洲女 | 精品无码av一区二区三区 | 真人与拘做受免费视频 | 亚洲熟妇自偷自拍另类 | 日韩人妻少妇一区二区三区 | 熟妇人妻无码xxx视频 | 国产婷婷色一区二区三区在线 | 99久久精品日本一区二区免费 | 久久熟妇人妻午夜寂寞影院 | 精品国产一区二区三区四区在线看 | 亚洲综合在线一区二区三区 | 丰满少妇熟乱xxxxx视频 | 内射后入在线观看一区 | 国产精品-区区久久久狼 | 国产97人人超碰caoprom | 思思久久99热只有频精品66 | 在线播放无码字幕亚洲 | 曰韩无码二三区中文字幕 | 日日鲁鲁鲁夜夜爽爽狠狠 | 极品嫩模高潮叫床 | 色情久久久av熟女人妻网站 | 欧美国产日产一区二区 | 国产精品.xx视频.xxtv | 秋霞特色aa大片 | 精品无码一区二区三区的天堂 | 亚洲日本va午夜在线电影 | 亚洲综合无码一区二区三区 | 国产精品成人av在线观看 | 最新国产乱人伦偷精品免费网站 | 无码中文字幕色专区 | 少妇无套内谢久久久久 | 国产精品怡红院永久免费 | 国产午夜视频在线观看 | 99久久精品午夜一区二区 | 2019午夜福利不卡片在线 | 国产熟妇高潮叫床视频播放 | 97资源共享在线视频 | 久久综合九色综合欧美狠狠 | 精品成在人线av无码免费看 | 少妇性l交大片欧洲热妇乱xxx | 天堂а√在线中文在线 | 国产在线aaa片一区二区99 | 国产精品二区一区二区aⅴ污介绍 | 人人爽人人爽人人片av亚洲 | 国产精品无码一区二区三区不卡 | 亚洲日本va中文字幕 | 国产人妻精品一区二区三区不卡 | 131美女爱做视频 | 国产在线精品一区二区三区直播 | 波多野结衣 黑人 | 蜜桃视频插满18在线观看 | 又色又爽又黄的美女裸体网站 | 中文字幕+乱码+中文字幕一区 | 国产精品久久久久久亚洲影视内衣 | 国产精品va在线观看无码 | 国产美女极度色诱视频www | 日本精品人妻无码77777 天堂一区人妻无码 | 青青青爽视频在线观看 | 亚洲国产av美女网站 | 亚洲国产精品久久人人爱 | 精品欧洲av无码一区二区三区 | 伊人久久大香线蕉av一区二区 | 成人欧美一区二区三区 | 亚洲经典千人经典日产 | 亚洲自偷精品视频自拍 | 成人动漫在线观看 | 国产亚洲人成在线播放 | 日本精品少妇一区二区三区 | 久久久久久久女国产乱让韩 | 国产成人无码av片在线观看不卡 | 狠狠色噜噜狠狠狠7777奇米 | 人妻插b视频一区二区三区 | 国产精品国产三级国产专播 | 亚洲精品一区三区三区在线观看 | 久久久久se色偷偷亚洲精品av | 免费人成在线视频无码 | 亚洲国产成人av在线观看 | 欧美成人免费全部网站 | 亚洲国产av精品一区二区蜜芽 | 久青草影院在线观看国产 | 久久久久成人精品免费播放动漫 | 最新国产乱人伦偷精品免费网站 | 国产9 9在线 | 中文 | 国产成人无码av在线影院 | 一本久道高清无码视频 | 精品欧美一区二区三区久久久 | 无码人妻av免费一区二区三区 | 日本熟妇大屁股人妻 | 久久久久国色av免费观看性色 | 中文字幕乱码亚洲无线三区 | 亚洲男人av香蕉爽爽爽爽 | 国产另类ts人妖一区二区 | 美女毛片一区二区三区四区 | 99国产精品白浆在线观看免费 | 98国产精品综合一区二区三区 | 图片小说视频一区二区 | 国产一精品一av一免费 | 国产精品人人爽人人做我的可爱 | 日本乱人伦片中文三区 | 亚洲一区二区三区国产精华液 | 18黄暴禁片在线观看 | 在线精品国产一区二区三区 | 亚拍精品一区二区三区探花 | 狠狠色噜噜狠狠狠7777奇米 | 国产香蕉97碰碰久久人人 | 国产亚洲精品精品国产亚洲综合 | 国产精品自产拍在线观看 | 色婷婷欧美在线播放内射 | 亚洲国精产品一二二线 | 日本又色又爽又黄的a片18禁 | 国产人妻大战黑人第1集 | 色婷婷香蕉在线一区二区 | 午夜精品久久久久久久 | 一二三四社区在线中文视频 | 综合人妻久久一区二区精品 | 亚洲国产午夜精品理论片 | 成熟妇人a片免费看网站 | 水蜜桃av无码 | 亚洲一区二区三区播放 | 免费观看的无遮挡av | 秋霞成人午夜鲁丝一区二区三区 | 国内精品九九久久久精品 | 亚洲精品国偷拍自产在线观看蜜桃 | 奇米综合四色77777久久 东京无码熟妇人妻av在线网址 | √8天堂资源地址中文在线 | 久久天天躁狠狠躁夜夜免费观看 | 亚洲欧美精品伊人久久 | 蜜桃无码一区二区三区 | 激情内射日本一区二区三区 | 成人性做爰aaa片免费看 | 奇米影视888欧美在线观看 | 亚洲国产精品久久人人爱 | 成人精品视频一区二区 | 大胆欧美熟妇xx | 国产亚洲欧美在线专区 | 国产精品va在线观看无码 | 日韩av激情在线观看 | 无码人妻黑人中文字幕 | 欧美亚洲国产一区二区三区 | 中国女人内谢69xxxxxa片 | 色一情一乱一伦一区二区三欧美 | 国产成人精品久久亚洲高清不卡 | 亚洲熟妇色xxxxx欧美老妇 | 色综合久久中文娱乐网 | 日本一卡2卡3卡四卡精品网站 | 免费看少妇作爱视频 | 麻豆果冻传媒2021精品传媒一区下载 | 99久久久无码国产aaa精品 | 久久99精品久久久久久动态图 | 人人妻人人澡人人爽欧美一区 | 人人妻人人澡人人爽欧美一区九九 | 免费无码一区二区三区蜜桃大 | 亚洲狠狠色丁香婷婷综合 | 麻花豆传媒剧国产免费mv在线 | 国产精品无码mv在线观看 | 成熟妇人a片免费看网站 | 成人亚洲精品久久久久 | 久久天天躁狠狠躁夜夜免费观看 | 国产精品久久久久久亚洲影视内衣 | 99麻豆久久久国产精品免费 | 伊人久久婷婷五月综合97色 | 亚洲国产精品久久久天堂 | 亚洲国产精华液网站w | 久久国产精品精品国产色婷婷 | 思思久久99热只有频精品66 | 无码精品国产va在线观看dvd | 日日碰狠狠丁香久燥 | 无码人中文字幕 | 午夜福利一区二区三区在线观看 | 天天拍夜夜添久久精品 | 伦伦影院午夜理论片 | 国产亚洲精品久久久久久久久动漫 | 午夜不卡av免费 一本久久a久久精品vr综合 | 荡女精品导航 | 国产午夜福利亚洲第一 | 免费观看又污又黄的网站 | 女人被爽到呻吟gif动态图视看 | 亚洲日韩av片在线观看 | 人妻有码中文字幕在线 | 久久综合狠狠综合久久综合88 | 在线 国产 欧美 亚洲 天堂 | 俺去俺来也在线www色官网 | 亚洲伊人久久精品影院 | 对白脏话肉麻粗话av | 国产午夜无码视频在线观看 | 日本精品少妇一区二区三区 | 精品国产麻豆免费人成网站 | 中文字幕精品av一区二区五区 | 香蕉久久久久久av成人 | 亚洲精品国产精品乱码视色 | 性欧美熟妇videofreesex | 色欲综合久久中文字幕网 | 亚洲自偷自拍另类第1页 | 中文久久乱码一区二区 | 99久久久无码国产精品免费 | 国色天香社区在线视频 | 午夜无码区在线观看 | 亚洲の无码国产の无码影院 | 色一情一乱一伦一区二区三欧美 | 欧美精品国产综合久久 | 久久99精品国产麻豆 | 呦交小u女精品视频 | 成人女人看片免费视频放人 | www国产亚洲精品久久久日本 | 欧美丰满熟妇xxxx | 免费乱码人妻系列无码专区 | 美女扒开屁股让男人桶 | 中文字幕无码人妻少妇免费 | 久久久久久九九精品久 | 亚洲第一无码av无码专区 | 午夜免费福利小电影 | 天天综合网天天综合色 | 亚洲色在线无码国产精品不卡 | 黑人巨大精品欧美一区二区 | 东京热无码av男人的天堂 | 在教室伦流澡到高潮hnp视频 | 欧美老人巨大xxxx做受 | 久久综合九色综合97网 | 人妻少妇精品视频专区 | 中文亚洲成a人片在线观看 | 无码乱肉视频免费大全合集 | 日韩亚洲欧美中文高清在线 | 欧美丰满熟妇xxxx性ppx人交 | 无码一区二区三区在线 | 久久国产精品二国产精品 | 国产成人av免费观看 | 午夜福利不卡在线视频 | 玩弄少妇高潮ⅹxxxyw | 性生交片免费无码看人 | 无码av中文字幕免费放 | 国产偷国产偷精品高清尤物 | 久久综合久久自在自线精品自 | 无遮挡国产高潮视频免费观看 | 成年美女黄网站色大免费视频 | 亚洲综合无码久久精品综合 | 一区二区三区高清视频一 | 日本一卡2卡3卡4卡无卡免费网站 国产一区二区三区影院 | 色综合久久网 | 久久天天躁狠狠躁夜夜免费观看 | 亚拍精品一区二区三区探花 | 熟妇人妻无码xxx视频 | 欧美国产日产一区二区 | 中文无码成人免费视频在线观看 | 精品人人妻人人澡人人爽人人 | 欧美性生交活xxxxxdddd | 天堂一区人妻无码 | 日本爽爽爽爽爽爽在线观看免 | 国产精品人人妻人人爽 | 亚洲色偷偷男人的天堂 | 亚洲人交乣女bbw | 性做久久久久久久久 | 黑人玩弄人妻中文在线 | 草草网站影院白丝内射 | 少妇人妻偷人精品无码视频 | 色综合久久中文娱乐网 | 国产偷抇久久精品a片69 | 骚片av蜜桃精品一区 | 久久亚洲日韩精品一区二区三区 | 97夜夜澡人人双人人人喊 | 欧美 日韩 亚洲 在线 | 人人妻人人澡人人爽欧美一区 | 久久人妻内射无码一区三区 | 一本色道婷婷久久欧美 | 亚洲经典千人经典日产 | 欧美国产亚洲日韩在线二区 | 丰满岳乱妇在线观看中字无码 | 亚洲国产日韩a在线播放 | 国产成人无码区免费内射一片色欲 | 国产午夜精品一区二区三区嫩草 | 色偷偷人人澡人人爽人人模 | 久久99久久99精品中文字幕 | 无码午夜成人1000部免费视频 | 久久精品成人欧美大片 | 成人无码视频在线观看网站 | 精品亚洲韩国一区二区三区 | 性史性农村dvd毛片 | 久久亚洲精品中文字幕无男同 | 国产成人精品久久亚洲高清不卡 | 日韩精品无码一区二区中文字幕 | 欧美亚洲日韩国产人成在线播放 | 亚洲精品午夜国产va久久成人 | 中文字幕乱码人妻无码久久 | 小鲜肉自慰网站xnxx | 亚洲国产精品毛片av不卡在线 | 国产成人亚洲综合无码 | 中文无码伦av中文字幕 | 麻豆国产人妻欲求不满 | 国产乱人伦av在线无码 | 鲁一鲁av2019在线 | 中文字幕日产无线码一区 | 精品无码成人片一区二区98 | 自拍偷自拍亚洲精品被多人伦好爽 | 亚洲 激情 小说 另类 欧美 | yw尤物av无码国产在线观看 | 婷婷丁香五月天综合东京热 | 亚洲色无码一区二区三区 | 99久久久无码国产aaa精品 | 狂野欧美激情性xxxx | 7777奇米四色成人眼影 | 正在播放老肥熟妇露脸 | 1000部夫妻午夜免费 | 精品国精品国产自在久国产87 | 国产做国产爱免费视频 | 国产黑色丝袜在线播放 | 国产亚洲欧美日韩亚洲中文色 | 亚洲 另类 在线 欧美 制服 | 欧美肥老太牲交大战 | 久久无码专区国产精品s | 又大又黄又粗又爽的免费视频 | 中文字幕+乱码+中文字幕一区 | 日本精品高清一区二区 | 亚洲熟女一区二区三区 | 婷婷综合久久中文字幕蜜桃三电影 | 牲欲强的熟妇农村老妇女 | 无人区乱码一区二区三区 | 少妇被黑人到高潮喷出白浆 | 蜜桃视频插满18在线观看 | 暴力强奷在线播放无码 | 亚洲成av人在线观看网址 | 久久精品无码一区二区三区 | 中文字幕乱码中文乱码51精品 | 亚洲一区二区三区偷拍女厕 | 永久免费精品精品永久-夜色 | 少妇人妻偷人精品无码视频 | 国精产品一区二区三区 | 国产精品无码久久av | 国产97在线 | 亚洲 | 激情人妻另类人妻伦 | 日产精品高潮呻吟av久久 | 国产亚洲精品久久久久久久久动漫 | 黑森林福利视频导航 | 无套内谢的新婚少妇国语播放 | 全黄性性激高免费视频 | 一二三四在线观看免费视频 | 人人澡人人妻人人爽人人蜜桃 | 对白脏话肉麻粗话av | 中文字幕无码日韩欧毛 | 亚洲区欧美区综合区自拍区 | 综合网日日天干夜夜久久 | 色一情一乱一伦 | 久久精品人人做人人综合 | 精品成在人线av无码免费看 | 欧美一区二区三区视频在线观看 | 成人精品天堂一区二区三区 | 一本色道久久综合亚洲精品不卡 | 久久精品中文字幕大胸 | 亚洲日韩一区二区 | 成人一在线视频日韩国产 | 中文无码伦av中文字幕 | 日韩人妻少妇一区二区三区 | 2019午夜福利不卡片在线 | 亚洲日韩精品欧美一区二区 | 久久久久成人精品免费播放动漫 | 色欲综合久久中文字幕网 | 亚洲成在人网站无码天堂 | 美女黄网站人色视频免费国产 | 青青久在线视频免费观看 | 少妇人妻大乳在线视频 | 亚洲а∨天堂久久精品2021 | 又黄又爽又色的视频 | 55夜色66夜色国产精品视频 | 久热国产vs视频在线观看 | 天堂亚洲2017在线观看 | 久久天天躁狠狠躁夜夜免费观看 | 亚洲国产精品成人久久蜜臀 | 免费观看又污又黄的网站 | 日日摸日日碰夜夜爽av | 亚洲欧美日韩国产精品一区二区 | 久久99精品久久久久久动态图 | 久久99精品国产.久久久久 | 黑人玩弄人妻中文在线 | 欧美精品一区二区精品久久 | 人人妻人人藻人人爽欧美一区 | 18精品久久久无码午夜福利 | 色一情一乱一伦一区二区三欧美 | 九九久久精品国产免费看小说 | 中国大陆精品视频xxxx | 日韩人妻无码中文字幕视频 | 无码帝国www无码专区色综合 | 日韩av无码一区二区三区 | 人妻中文无码久热丝袜 | 久久久久久a亚洲欧洲av冫 | 51国偷自产一区二区三区 | 男人和女人高潮免费网站 | 欧洲欧美人成视频在线 | 亚洲熟妇色xxxxx亚洲 | 97久久国产亚洲精品超碰热 | 天堂亚洲免费视频 | 少妇性l交大片欧洲热妇乱xxx | 在线成人www免费观看视频 | 在线欧美精品一区二区三区 | 蜜臀av在线播放 久久综合激激的五月天 | 乌克兰少妇xxxx做受 | 香港三级日本三级妇三级 | 狠狠躁日日躁夜夜躁2020 | 澳门永久av免费网站 | 亚洲人成人无码网www国产 | 亚洲爆乳无码专区 | 亚洲成a人片在线观看日本 | 国产精品内射视频免费 | 国产农村妇女高潮大叫 | 中文字幕乱码中文乱码51精品 | 成 人 网 站国产免费观看 | 国产精品怡红院永久免费 | 一个人看的视频www在线 | 人人澡人人妻人人爽人人蜜桃 | 成熟女人特级毛片www免费 | 5858s亚洲色大成网站www | 国产福利视频一区二区 | 国产莉萝无码av在线播放 | a在线观看免费网站大全 | 俺去俺来也在线www色官网 | 亚洲人成网站免费播放 | 欧美国产日韩久久mv | 在线观看国产一区二区三区 | 午夜精品久久久内射近拍高清 | 狠狠色欧美亚洲狠狠色www | 国产精品爱久久久久久久 | 国产后入清纯学生妹 | 中文字幕乱码中文乱码51精品 | 午夜男女很黄的视频 | 最新国产乱人伦偷精品免费网站 | 免费播放一区二区三区 | 国产av无码专区亚洲a∨毛片 | 亚洲男人av香蕉爽爽爽爽 | 中文精品久久久久人妻不卡 | 久久人人97超碰a片精品 | 97无码免费人妻超级碰碰夜夜 | 无码人妻黑人中文字幕 | 欧美熟妇另类久久久久久多毛 | 天下第一社区视频www日本 | 美女毛片一区二区三区四区 | 无遮挡啪啪摇乳动态图 | 伊在人天堂亚洲香蕉精品区 | 国产亚洲日韩欧美另类第八页 | 色五月丁香五月综合五月 |