Java高頻面試題

前言

疫情確診的人數(shù)每天都在增加,離去的人也在增多鄙信,這個(gè)世界上有很多事我們無(wú)能為力也無(wú)從選擇瞪醋,日升日落,白晝黑夜装诡,我們能看見(jiàn)白晝中的光芒银受,我們也能看見(jiàn)黑暗里的流氓。暮色四合鸦采,齷齪八開(kāi)宾巍。鮮花還是塑料花,香或臭渔伯,當(dāng)潮水散去顶霞,現(xiàn)在即歷史,而歷史通常是由后人說(shuō)的锣吼。

所以還是上次跟鄉(xiāng)親們說(shuō)的选浑,我們不要傳播未經(jīng)證實(shí)或者不該傳播的消息,輿論的力量是我們無(wú)法估計(jì)的玄叠,有些也是我們無(wú)法承擔(dān)的古徒,所以鄉(xiāng)親們也要重視起來(lái),點(diǎn)到即止读恃。無(wú)法控制別人隧膘,但可以做好自己,幫不了別人寺惫,但可以不禍害別人舀寓。

我不是個(gè)喜歡蹭熱度的人,上面那段話鄉(xiāng)親們看看就好肌蜻,現(xiàn)階段最重要的就是老老實(shí)實(shí)待在家里,不聚集必尼,也盡量不出門蒋搜,自己和家人都要做好安全防護(hù),老百姓經(jīng)歷了太多風(fēng)風(fēng)雨雨判莉,相信這次一定也會(huì)安然無(wú)恙的渡過(guò)此劫豆挽。那待在家里的這段時(shí)間,如果能遠(yuǎn)程辦公的券盅,就做好公司交代的事帮哈,無(wú)法辦公的鄉(xiāng)親們也不要停止學(xué)習(xí),因?yàn)橐咔檫^(guò)去之后锰镀,一定會(huì)有巨大的變動(dòng)或者機(jī)會(huì)來(lái)臨娘侍,而到那時(shí)咖刃,你準(zhǔn)備好了嗎?

這幾天一直在想憾筏,碼之初能做點(diǎn)什么嚎杨?最終決定在這個(gè)期間就推出一個(gè)面試系列,都是經(jīng)過(guò)我精心整理的氧腰,希望能給鄉(xiāng)親們一點(diǎn)幫助枫浙。下面進(jìn)入正題。

高頻面試題

1古拴、說(shuō)說(shuō)對(duì)象的四中引用箩帚?

1)強(qiáng)引用只要引用存在,垃圾回收器永遠(yuǎn)不會(huì)回收黄痪。

 Object obj = new Object();
User user=new User();

可直接通過(guò)obj取得對(duì)應(yīng)的對(duì)象 如 obj.equels(new Object()); 而這樣 obj 對(duì)象對(duì)后面 new Object 的一個(gè)強(qiáng) 引用紧帕,只有當(dāng) obj 這個(gè)引用被釋放之后,對(duì)象才會(huì)被釋放掉满力,這也是我們經(jīng)常所用到的編碼形式焕参。

2)**軟引用 **非必須引用,內(nèi)存溢出之前進(jìn)行回收油额,可以通過(guò)以下代碼實(shí)現(xiàn)

Object obj = new Object();
SoftReference<Object> sf = new SoftReference<Object>(obj); 
obj = null;sf.get();//有時(shí)候會(huì)返回null

這時(shí)候sf是對(duì)obj的一個(gè)軟引用叠纷,通過(guò)sf.get()方法可以取到這個(gè)對(duì)象,當(dāng)然潦嘶,當(dāng)這個(gè)對(duì)象被標(biāo)記為需要回收的對(duì)象 時(shí)涩嚣,則返回null; 軟引用主要用戶實(shí)現(xiàn)類似緩存的功能,在內(nèi)存足夠的情況下直接通過(guò)軟引用取值掂僵,無(wú)需從繁忙的 真實(shí)來(lái)源查詢數(shù)據(jù)航厚,提升速度;當(dāng)內(nèi)存不足時(shí),自動(dòng)刪除這部分緩存數(shù)據(jù)锰蓬,從真正的來(lái)源查詢這些數(shù)據(jù)幔睬。

3)**弱引用 **第二次垃圾回收時(shí)回收,可以通過(guò)如下代碼實(shí)現(xiàn)

Object obj = new Object();
WeakReference<Object> wf = new WeakReference<Object>(obj); 
obj = null;wf.get();//有時(shí)候會(huì)返回null 
wf.isEnQueued();//返回是否被垃圾回收器標(biāo)記為即將回收的垃圾

弱引用是在第二次垃圾回收時(shí)回收芹扭,短時(shí)間內(nèi)通過(guò)弱引用取對(duì)應(yīng)的數(shù)據(jù)麻顶,可以取到,當(dāng)執(zhí)行過(guò)第二次垃圾回收時(shí)舱卡, 將返回null辅肾。弱引用主要用于監(jiān)控對(duì)象是否已經(jīng)被垃圾回收器標(biāo)記為即將回收的垃圾,可以通過(guò)弱引用的isEnQueued 方法返回對(duì)象是否被垃圾回收器標(biāo)記轮锥。

ThreadLocal 中有使用到弱引用:

public class ThreadLocal<T> {
 static class ThreadLocalMap {
        static class Entry extends WeakReference<ThreadLocal<?>> {
            /** The value associated with this ThreadLocal. */
            Object value;
            Entry(ThreadLocal<?> k, Object v) {
                super(k);
value = v; }
}
//....
}
//.....
}

4)虛引用垃圾回收時(shí)回收矫钓,無(wú)法通過(guò)引用取到對(duì)象值,可以通過(guò)如下代碼實(shí)現(xiàn):

Object obj = new Object();
PhantomReference<Object> pf = new PhantomReference<Object>(obj); 
obj=null;
pf.get();//永遠(yuǎn)返回null
pf.isEnQueued();//返回是否從內(nèi)存中已經(jīng)刪除

虛引用是每次垃圾回收的時(shí)候都會(huì)被回收,通過(guò)虛引用的get方法永遠(yuǎn)獲取到的數(shù)據(jù)為null新娜,因此也被成為幽靈引 用赵辕。虛引用主要用于檢測(cè)對(duì)象是否已經(jīng)從內(nèi)存中刪除。

2杯活、HashSet是如何保證不重復(fù)的匆帚?

向 HashSet 中 add ()元素時(shí),判斷元素是否存在的依據(jù)旁钧,不僅要比較hash值吸重,同時(shí)還要結(jié)合 equles 方法比較。

HashSet 中的 add ()方法會(huì)使用 HashMap 的 add ()方法歪今。以下是 HashSet 部分源碼:

private static final Object PRESENT = new Object();
private transient HashMap<E,Object> map;
public HashSet() {
        map = new HashMap<>();
}
public boolean add(E e) {
}

HashMap 的 key 是唯一的嚎幸,由上面的代碼可以看出 HashSet 添加進(jìn)去的值就是作為 HashMap 的key。所以不會(huì) 重復(fù)( HashMap 比較key是否相等是先比較 hashcode 在比較 equals )寄猩。

3嫉晶、HashMap是線程安全的嗎,為什么不是線程安全的(最好畫(huà)圖說(shuō)明多線程 環(huán)境下不安全)?

不是線程安全的;

如果有兩個(gè)線程A和B田篇,都進(jìn)行插入數(shù)據(jù)替废,剛好這兩條不同的數(shù)據(jù)經(jīng)過(guò)哈希計(jì)算后得到的哈希碼是一樣的,且該位 置還沒(méi)有其他的數(shù)據(jù)泊柬。所以這兩個(gè)線程都會(huì)進(jìn)入我在上面標(biāo)記為1的代碼中椎镣。假設(shè)一種情況,線程A通過(guò)if判斷兽赁,該 位置沒(méi)有哈希沖突状答,進(jìn)入了if語(yǔ)句,還沒(méi)有進(jìn)行數(shù)據(jù)插入刀崖,這時(shí)候 CPU 就把資源讓給了線程B惊科,線程A停在了if語(yǔ)句 里面,線程B判斷該位置沒(méi)有哈希沖突(線程A的數(shù)據(jù)還沒(méi)插入)亮钦,也進(jìn)入了if語(yǔ)句馆截,線程B執(zhí)行完后,輪到線程A執(zhí) 行蜂莉,現(xiàn)在線程A直接在該位置插入而不用再判斷孙咪。這時(shí)候,你會(huì)發(fā)現(xiàn)線程A把線程B插入的數(shù)據(jù)給覆蓋了巡语。發(fā)生了線 程不安全情況。本來(lái)在 HashMap 中淮菠,發(fā)生哈希沖突是可以用鏈表法或者紅黑樹(shù)來(lái)解決的男公,但是在多線程中,可能 就直接給覆蓋了。

上面所說(shuō)的是一個(gè)圖來(lái)解釋可能更加直觀枢赔。如下面所示澄阳,兩個(gè)線程在同一個(gè)位置添加數(shù)據(jù),后面添加的數(shù)據(jù)就覆蓋住了前面添加的踏拜。

Java高頻面試題

如果上述插入是插入到鏈表上碎赢,如兩個(gè)線程都在遍歷到最后一個(gè)節(jié)點(diǎn),都要在最后添加一個(gè)數(shù)據(jù)速梗,那么后面添加數(shù)據(jù)的線程就會(huì)把前面添加的數(shù)據(jù)給覆蓋住肮塞。則

Java高頻面試題

在擴(kuò)容的時(shí)候也可能會(huì)導(dǎo)致數(shù)據(jù)不一致,因?yàn)閿U(kuò)容是從一個(gè)數(shù)組拷貝到另外一個(gè)數(shù)組姻锁。

5枕赵、HashMap的擴(kuò)容過(guò)程

當(dāng)向容器添加元素的時(shí)候,會(huì)判斷當(dāng)前容器的元素個(gè)數(shù)位隶,如果大于等于閾值(知道這個(gè)閾字怎么念嗎?不念 fa 值拷窜,念 yu 值四聲)---即當(dāng)前數(shù)組的長(zhǎng)度乘以加載因子的值的時(shí)候,就要自動(dòng)擴(kuò)容啦涧黄。

擴(kuò)容( resize )就是重新計(jì)算容量篮昧,向 HashMap 對(duì)象里不停的添加元素,而 HashMap 對(duì)象內(nèi)部的數(shù)組無(wú)法裝載更 多的元素時(shí)笋妥,對(duì)象就需要擴(kuò)大數(shù)組的長(zhǎng)度懊昨,以便能裝入更多的元素。當(dāng)然 Java 里的數(shù)組是無(wú)法自動(dòng)擴(kuò)容的挽鞠,方法 是使用一個(gè)新的數(shù)組代替已有的容量小的數(shù)組疚颊,就像我們用一個(gè)小桶裝水,如果想裝更多的水信认,就得換大水桶材义。

 HashMap hashMap=new HashMap(cap);
  • cap =3, hashMap 的容量為4;
  • cap =4嫁赏, hashMap 的容量為4;
  • cap=5其掂, 的容量為8;
  • cap =9, hashMap 的容量為16;
  • 如果 cap 是2的n次方潦蝇,則容量為 cap 款熬,否則為大于 cap 的第一個(gè)2的n次方的數(shù)。

6攘乒、Arrays.sort 和 Collections.sort 實(shí)現(xiàn)原理和區(qū)別贤牛?

Collection和Collections區(qū)別

java.util.Collection 是一個(gè)集合接口。它提供了對(duì)集合對(duì)象進(jìn)行基本操作的通用接口方法则酝。

java.util.Collections 是針對(duì)集合類的一個(gè)幫助類殉簸,他提供一系列靜態(tài)方法實(shí)現(xiàn)對(duì)各種集合的搜索、排序、 線程安全等操作般卑。然后還有混排(Shuffling)武鲁、反轉(zhuǎn)(Reverse)、替換所有的元素(fill)蝠检、拷貝(copy)沐鼠、返 回Collections中最小元素(min)、返回Collections中最大元素(max)叹谁、返回指定源列表中最后一次出現(xiàn)指定目 標(biāo)列表的起始位置( lastIndexOfSubList )饲梭、返回指定源列表中第一次出現(xiàn)指定目標(biāo)列表的起始位置

( IndexOfSubList )、根據(jù)指定的距離循環(huán)移動(dòng)指定列表中的元素(Rotate);

事實(shí)上Collections.sort方法底層就是調(diào)用的array.sort方法本慕,

public static void sort(Object[] a) {
        if (LegacyMergeSort.userRequested)
            legacyMergeSort(a);
        else
            ComparableTimSort.sort(a, 0, a.length, null, 0, 0);
}
//void java.util.ComparableTimSort.sort()
static void sort(Object[] a, int lo, int hi, Object[] work, int workBase, int workLen)
{
        assert a != null && lo >= 0 && lo <= hi && hi <= a.length;
        int nRemaining  = hi - lo;
        if (nRemaining < 2)
return;  // Arrays of size 0 and 1 are always sorted
   // If array is small, do a "mini-TimSort" with no merges
        if (nRemaining < MIN_MERGE) {
            int initRunLen = countRunAndMakeAscending(a, lo, hi);
            binarySort(a, lo, hi, lo + initRunLen);
            return;
  }
}

legacyMergeSort (a):歸并排序 ComparableTimSort.sort() : Timsort 排序

Timsort 排序是結(jié)合了合并排序(merge sort)和插入排序(insertion sort)而得出的排序算法排拷。

Timsort的核心過(guò)程:

TimSort 算法為了減少對(duì)升序部分的回溯和對(duì)降序部分的性能倒退,將輸入按其升序和降序特點(diǎn)進(jìn)行了分 區(qū)锅尘。排序的輸入的單位不是一個(gè)個(gè)單獨(dú)的數(shù)字监氢,而是一個(gè)個(gè)的塊-分區(qū)。其中每一個(gè)分區(qū)叫一個(gè)run藤违。針對(duì)這 些 run 序列浪腐,每次拿一個(gè) run 出來(lái)按規(guī)則進(jìn)行合并。每次合并會(huì)將兩個(gè) run合并成一個(gè) run顿乒。合并的結(jié)果保 存到棧中议街。合并直到消耗掉所有的 run,這時(shí)將棧上剩余的 run合并到只剩一個(gè) run 為止璧榄。這時(shí)這個(gè)僅剩的run 便是排好序的結(jié)果特漩。

綜上述過(guò)程,Timsort算法的過(guò)程包括:

  1. 如何數(shù)組長(zhǎng)度小于某個(gè)值骨杂,直接用二分插入排序算法涂身。
  2. 找到各個(gè)run,并入棧搓蚪。
  3. 按規(guī)則合并run蛤售。

7、Cloneable接口實(shí)現(xiàn)原理妒潭?

Cloneable接口是Java開(kāi)發(fā)中常用的一個(gè)接口悴能, 它的作用是使一個(gè)類的實(shí)例能夠?qū)⒆陨砜截惖搅硪粋€(gè)新的實(shí)例中, 注意雳灾,這里所說(shuō)的“拷貝”拷的是對(duì)象實(shí)例漠酿,而不是類的定義,進(jìn)一步說(shuō)谎亩,拷貝的是一個(gè)類的實(shí)例中各字段的值记靡。

在開(kāi)發(fā)過(guò)程中谈竿,拷貝實(shí)例是常見(jiàn)的一種操作,如果一個(gè)類中的字段較多摸吠,而我們又采用在客戶端中逐字段復(fù)制的方 法進(jìn)行拷貝操作的話,將不可避免的造成客戶端代碼繁雜冗長(zhǎng)嚎花,而且也無(wú)法對(duì)類中的私有成員進(jìn)行復(fù)制寸痢,而如果讓需要 具備拷貝功能的類實(shí)現(xiàn)Cloneable接口,并重寫(xiě)clone()方法紊选,就可以通過(guò)調(diào)用clone()方法的方式簡(jiǎn)潔地實(shí)現(xiàn)實(shí)例 拷貝功

深拷貝(深復(fù)制)和淺拷貝(淺復(fù)制)是兩個(gè)比較通用的概念啼止,尤其在C++語(yǔ)言中,若不弄懂兵罢,則會(huì)在delete的時(shí)候出問(wèn) 題献烦,但是我們?cè)谶@幸好用的是Java。雖然Java自動(dòng)管理對(duì)象的回收卖词,但對(duì)于深拷貝(深復(fù)制)和淺拷貝(淺復(fù)制)巩那,我們 還是要給予足夠的重視,因?yàn)橛袝r(shí)這兩個(gè)概念往往會(huì)給我們帶來(lái)不小的困惑此蜈。

淺拷貝是指拷貝對(duì)象時(shí)僅僅拷貝對(duì)象本身(包括對(duì)象中的基本變量)即横,而不拷貝對(duì)象包含的引用指向的對(duì)象。深拷 貝不僅拷貝對(duì)象本身裆赵,而且拷貝對(duì)象包含的引用指向的所有對(duì)象东囚。舉例來(lái)說(shuō)更加清楚:對(duì)象 A1 中包含對(duì) B1 的引 用, B1 中包含對(duì) C1 的引用战授。淺拷貝 A1 得到 A2 页藻, A2 中依然包含對(duì) B1 的引用, B1 中依然包含對(duì) C1 的引 用植兰。深拷貝則是對(duì)淺拷貝的遞歸份帐,深拷貝 A1 得到 A2 , A2 中包含對(duì) B2 ( B1 的 copy )的引用钉跷, B2 中包含 對(duì) C2 ( C1 的 copy )的引用弥鹦。

若不對(duì)clone()方法進(jìn)行改寫(xiě),則調(diào)用此方法得到的對(duì)象即為淺拷貝 爷辙。

8彬坏、簡(jiǎn)單講一下異常分類以及處理機(jī)制?

Java高頻面試題

Java標(biāo)準(zhǔn)庫(kù)內(nèi)建了一些通用的異常膝晾,這些類以Throwable為頂層父類栓始。Throwable又派生出Error類和Exception類。

錯(cuò)誤:Error類以及他的子類的實(shí)例血当,代表了JVM本身的錯(cuò)誤幻赚。錯(cuò)誤不能被程序員通過(guò)代碼處理禀忆,Error很少出現(xiàn)。因此落恼,程序員應(yīng)該關(guān)注Exception為父類的分支下的各種異常類箩退。

異常:Exception以及他的子類,代表程序運(yùn)行時(shí)發(fā)送的各種不期望發(fā)生的事件佳谦〈骼裕可以被Java異常處理機(jī)制使用, 是異常處理的核心钻蔑。

Java高頻面試題

總體上我們根據(jù) Javac 對(duì)異常的處理要求啥刻,將異常類分為二類。

  • 非檢查異常( unckecked exception ): Error 和 RuntimeException 以及他們的子類咪笑。javac 在編譯時(shí)可帽, 不會(huì)提示和發(fā)現(xiàn)這樣的異常,不要求在程序處理這些異常窗怒。所以如果愿意映跟,我們可以編寫(xiě)代碼處理(使用catch...finally )這樣的異常,也可以不處理兜粘。對(duì)于這些異常申窘,我們應(yīng)該修正代碼,而不是去通過(guò)異常處理器處 理 孔轴。這樣的異常發(fā)生的原因多半是代碼寫(xiě)的有問(wèn)題剃法。如除0錯(cuò)誤 ArithmeticException ,錯(cuò)誤的強(qiáng)制類型轉(zhuǎn)換錯(cuò) 誤 ClassCastException 路鹰,數(shù)組索引越界 ArrayIndexOutOfBoundsException 贷洲,使用了空對(duì)象NullPointerException 等等。
  • 檢查異常( checked exception ):除了 Error 和 RuntimeException 的其它異常晋柱。javac 強(qiáng)制要求程序員 為這樣的異常做預(yù)備處理工作(使用 try...catch...finally 或者 throws )优构。在方法中要么用 try-catch 語(yǔ)句捕 獲它并處理,要么用throws子句聲明拋出它雁竞,否則編譯不會(huì)通過(guò)钦椭。這樣的異常一般是由程序的運(yùn)行環(huán)境導(dǎo)致的。因 為程序可能被運(yùn)行在各種未知的環(huán)境下碑诉,而程序員無(wú)法干預(yù)用戶如何使用他編寫(xiě)的程序彪腔,于是程序員就應(yīng)該為這樣 的異常時(shí)刻準(zhǔn)備著。如 SQLException , ClassNotFoundException 等进栽。

需要明確的是:檢查和非檢查是對(duì)于 javac 來(lái)說(shuō)的德挣,這樣就很好理解和區(qū)分了。

9快毛、wait和sleep的區(qū)別格嗅?

源碼如下:

public class Thread implements Runnable {
public static native void sleep(long millis) throws InterruptedException;
     public static void sleep(long millis, int nanos) throws InterruptedException {
        if (millis < 0) {
            throw new IllegalArgumentException("timeout value is negative");
        }
        if (nanos < 0 || nanos > 999999) {
        throw new IllegalArgumentException(
        "nanosecond timeout value out of range");
        }
        if (nanos >= 500000 || (nanos != 0 && millis == 0)) {
millis++; }
        sleep(millis);
    }
//...
}
public class Object {
     public final native void wait(long timeout) throws InterruptedException;
     public final void wait(long timeout, int nanos) throws InterruptedException {
        if (timeout < 0) {
            throw new IllegalArgumentException("timeout value is negative");
        }
        if (nanos < 0 || nanos > 999999) {
            throw new IllegalArgumentException(
                                "nanosecond timeout value out of range");
        }
        if (nanos > 0) {
timeout++; }
        wait(timeout);
    }
//...
}

1番挺、 sleep 來(lái)自 Thread 類,和 wait 來(lái)自 Object 類屯掖。

2玄柏、最主要是sleep方法沒(méi)有釋放鎖,而wait方法釋放了 鎖贴铜,使得其他線程可以使用同步控制塊或者方法禁荸。
3、wait阀湿,notify和 notifyAll 只能在同步控制方法或者同步控制塊里面使用,而 sleep 可以在任何地方使用(使 用范圍)

4瑰妄、 sleep 必須捕獲異常陷嘴,而 wait , notify 和 notifyAll 不需要捕獲異常

  • sleep 方法屬于 Thread 類中方法间坐,表示讓一個(gè)線程進(jìn)入睡眠狀態(tài)灾挨,等待一定的時(shí)間之后,自動(dòng)醒來(lái)進(jìn)入到可 運(yùn)行狀態(tài)竹宋,不會(huì)馬上進(jìn)入運(yùn)行狀態(tài)劳澄,因?yàn)榫€程調(diào)度機(jī)制恢復(fù)線程的運(yùn)行也需要時(shí)間,一個(gè)線程對(duì)象調(diào)用了 sleep方法之后蜈七,并不會(huì)釋放他所持有的所有對(duì)象鎖秒拔,所以也就不會(huì)影響其他進(jìn)程對(duì)象的運(yùn)行。但在 sleep 的過(guò)程中過(guò) 程中有可能被其他對(duì)象調(diào)用它的 interrupt() ,產(chǎn)生 InterruptedException 異常飒硅,如果你的程序不捕獲這個(gè)異 常砂缩,線程就會(huì)異常終止,進(jìn)入 TERMINATED 狀態(tài)三娩,如果你的程序捕獲了這個(gè)異常庵芭,那么程序就會(huì)繼續(xù)執(zhí)行catch語(yǔ) 句塊(可能還有 finally 語(yǔ)句塊)以及以后的代碼。注意 sleep() 方法是一個(gè)靜態(tài)方法雀监,也就是說(shuō)他只對(duì)當(dāng)前對(duì)象有效双吆,通過(guò) t.sleep() 讓t對(duì)象進(jìn)入 sleep ,這樣 的做法是錯(cuò)誤的会前,它只會(huì)是使當(dāng)前線程被 sleep 而不是 t 線程好乐。
  • wait 屬于 Object 的成員方法,一旦一個(gè)對(duì)象調(diào)用了wait方法回官,必須要采用 notify() 和 notifyAll() 方法 喚醒該進(jìn)程;如果線程擁有某個(gè)或某些對(duì)象的同步鎖曹宴,那么在調(diào)用了 wait() 后,這個(gè)線程就會(huì)釋放它持有的所有 同步資源歉提,而不限于這個(gè)被調(diào)用了 wait() 方法的對(duì)象笛坦。wait() 方法也同樣會(huì)在 wait 的過(guò)程中有可能被其他對(duì) 象調(diào)用 interrupt() 方法而產(chǎn)生 区转。

10、數(shù)組在內(nèi)存中如何分配版扩?

對(duì)于 Java 數(shù)組的初始化废离,有以下兩種方式,這也是面試中經(jīng)辰嘎考到的經(jīng)典題目蜻韭。

靜態(tài)初始化:初始化時(shí)由程序員顯式指定每個(gè)數(shù)組元素的初始值,由系統(tǒng)決定數(shù)組長(zhǎng)度柿扣,如:

 //只是指定初始值肖方,并沒(méi)有指定數(shù)組的長(zhǎng)度,但是系統(tǒng)為自動(dòng)決定該數(shù)組的長(zhǎng)度為4 
 String[] computers = {"Dell", "Lenovo", "Apple", "Acer"}; //1 
//只是指定初始值未状,并沒(méi)有指定數(shù)組的長(zhǎng)度俯画,但是系統(tǒng)為自動(dòng)決定該數(shù)組的長(zhǎng)度為3 
 String[] names = new String[]{"多啦A夢(mèng)", "大雄", "靜香"}; //2

動(dòng)態(tài)初始化:初始化時(shí)由程序員顯示的指定數(shù)組的長(zhǎng)度,由系統(tǒng)為數(shù)據(jù)每個(gè)元素分配

初始值司草,如:

//只是指定了數(shù)組的長(zhǎng)度艰垂,并沒(méi)有顯示的為數(shù)組指定初始值,但是系統(tǒng)會(huì)默認(rèn)給數(shù)組數(shù)組元素分配初始值為null 
 String[] cars = new String[4]; //3

因?yàn)?Java 數(shù)組變量是引用類型的變量埋虹,所以上述幾行初始化語(yǔ)句執(zhí)行后猜憎,三個(gè)數(shù)組在內(nèi)存中的分配情況如下圖所 示:

Java高頻面試題

由上圖可知,靜態(tài)初始化方式搔课,程序員雖然沒(méi)有指定數(shù)組長(zhǎng)度胰柑,但是系統(tǒng)已經(jīng)自動(dòng)幫我們給分配了,而動(dòng)態(tài)初始化 方式辣辫,程序員雖然沒(méi)有顯示的指定初始化值旦事,但是因?yàn)?Java 數(shù)組是引用類型的變量,所以系統(tǒng)也為每個(gè)元素分配 了初始化值 null 急灭,當(dāng)然不同類型的初始化值也是不一樣的姐浮,假設(shè)是基本類型int類型,那么為系統(tǒng)分配的初始化值 也是對(duì)應(yīng)的默認(rèn)值0葬馋。

11卖鲤、說(shuō)說(shuō)Java反射機(jī)制?

Java 反射機(jī)制是在運(yùn)行狀態(tài)中畴嘶,對(duì)于任意一個(gè)類蛋逾,都能夠獲得這個(gè)類的所有屬性和方法,對(duì)于任意一個(gè)對(duì)象都能夠 調(diào)用它的任意一個(gè)屬性和方法窗悯。這種在運(yùn)行時(shí)動(dòng)態(tài)的獲取信息以及動(dòng)態(tài)調(diào)用對(duì)象的方法的功能稱為 Java 的反射機(jī) 制区匣。

Class 類與 java.lang.reflect 類庫(kù)一起對(duì)反射的概念進(jìn)行了支持,該類庫(kù)包含了 Field,Method,Constructor 類 (每 個(gè)類都實(shí)現(xiàn)了 Member 接口)蒋院。這些類型的對(duì)象時(shí)由 JVM 在運(yùn)行時(shí)創(chuàng)建的亏钩,用以表示未知類里對(duì)應(yīng)的成員莲绰。

這樣你就可以使用 Constructor 創(chuàng)建新的對(duì)象,用 get() 和 set() 方法讀取和修改與 Field 對(duì)象關(guān)聯(lián)的字段姑丑,用 invoke() 方法調(diào)用與 Method 對(duì)象關(guān)聯(lián)的方法蛤签。另外,還可以調(diào)用 getFields() getMethods() 和 getConstructors() 等很便利的方法栅哀,以返回表示字段震肮,方法,以及構(gòu)造器的對(duì)象的數(shù)組留拾。這樣匿名對(duì)象的信息 就能在運(yùn)行時(shí)被完全確定下來(lái)戳晌,而在編譯時(shí)不需要知道任何事情。

import java.lang.reflect.Constructor;
public class ReflectTest {
    public static void main(String[] args) throws Exception {
      Class clazz = null;
      clazz = Class.forName("com.jas.reflect.Fruit");
      Constructor<Fruit> constructor1 = clazz.getConstructor();
      Constructor<Fruit> constructor2 = clazz.getConstructor(String.class);
      Fruit fruit1 = constructor1.newInstance();
      Fruit fruit2 = constructor2.newInstance("Apple");
  } 
}
class Fruit{
    public Fruit(){
      System.out.println("無(wú)參構(gòu)造器 Run..........."); }
      public Fruit(String type){
      System.out.println("有參構(gòu)造器 Run..........." + type);
  } 
}
運(yùn)行結(jié)果: 無(wú)參構(gòu)造器 Run........... 有參構(gòu)造器 Run...........Apple

12痴柔、Java獲取反射的三種方法躬厌?

  1. 通過(guò)new對(duì)象實(shí)現(xiàn)反射機(jī)制。
  2. 通過(guò)路徑實(shí)現(xiàn)反射機(jī)制竞帽。
  3. 通過(guò)類名實(shí)現(xiàn)反射機(jī)制。

代碼示例:

public class Student {
    private int id;
    String name;
    protected boolean sex;
    public float score;
}
public class Get {
  //獲取反射機(jī)制三種方式
  public static void main(String[] args) throws ClassNotFoundException {
    //方式一(通過(guò)建立對(duì)象)
    Student stu = new Student();
    Class classobj1 = stu.getClass(); 
    System.out.println(classobj1.getName()); 
    //方式二(所在通過(guò)路徑-相對(duì)路徑)
    Class classobj2 = Class.forName("fanshe.Student"); 
    System.out.println(classobj2.getName()); 
    //方式三(通過(guò)類名)
    Class classobj3 = Student.class; 
    System.out.println(classobj3.getName());
  }
}

13鸿捧、String 和 StringBuilder屹篓、StringBuffer 的區(qū)別?

Java 平臺(tái)提供了兩種類型的字符串:String 和StringBuffer/StringBuilder,它們可以儲(chǔ)存和操作字符串匙奴。其中 String 是只 讀字符串堆巧,也就意味著 String 引用的字符串內(nèi)容是不能被改變的。而StringBuffer/StringBuilder 類表示的字符串對(duì)象可以直接進(jìn)行修改泼菌。StringBuilder 是 Java 5 中引入的谍肤,它和 StringBuffer 的方法完全相同,區(qū) 別在于它是在單線程環(huán)境下使用的哗伯,因?yàn)樗乃蟹矫娑紱](méi)有被 synchronized修飾荒揣,因此它的效率也比 StringBuffer 要高。

14焊刹、描述一下 JVM 加載 class 文件的原理機(jī)制?

JVM 中類的裝載是由類加載器(ClassLoader)和它的子類來(lái)實(shí)現(xiàn)的系任,Java中的類加載器是一個(gè)重要的 Java 運(yùn)行時(shí)系統(tǒng)組件,它負(fù)責(zé)在運(yùn)行時(shí)查找和裝入類文件中的類虐块。

由于 Java 的跨平臺(tái)性俩滥,經(jīng)過(guò)編譯的 Java 源程序并不是一個(gè)可執(zhí)行程序,而是 一個(gè)或多個(gè)類文件贺奠。當(dāng) Java 程序需要使用某個(gè)類時(shí)霜旧,JVM 會(huì)確保這個(gè)類已經(jīng)被 加載、連接(驗(yàn)證儡率、準(zhǔn)備和解析)和初始化挂据。類的加載是指把類的.class 文件 中的數(shù)據(jù)讀入到內(nèi)存中以清,通常是創(chuàng)建一個(gè)字節(jié)數(shù)組讀入.class 文件,然后產(chǎn)生 與所加載類對(duì)應(yīng)的 Class 對(duì)象棱貌。加載完成后玖媚,Class 對(duì)象還不完整,所以此時(shí) 的類還不可用婚脱。當(dāng)類被加載后就進(jìn)入連接階段今魔,這一階段包括驗(yàn)證、準(zhǔn)備(為靜態(tài)變量分配內(nèi)存并設(shè)置默認(rèn)的初始值)和解析(將符號(hào)引用替換為直接引 用)三個(gè)步驟障贸。最后 JVM 對(duì)類進(jìn)行初始化错森,包括:1)如果類存在直接的父類并 且這個(gè)類還沒(méi)有被初始化,那么就先初始化父類;2)如果類中存在初始化語(yǔ) 句篮洁,就依次執(zhí)行這些初始化語(yǔ)句涩维。

類的加載是由類加載器完成的,類加載器包括:根加載器(BootStrap)袁波、擴(kuò)展 加載器(Extension)瓦阐、系統(tǒng)加載器(System)和用戶自定義類加載器 (java.lang.ClassLoader 的子類)。從 Java 2(JDK 1.2)開(kāi)始篷牌,類加載過(guò)程 采取了父親委托機(jī)制(PDM)睡蟋。PDM 更好的保證了 Java 平臺(tái)的安全性,在該機(jī) 制中枷颊,JVM 自帶的 Bootstrap 是根加載器戳杀,其他的加載器都有且僅有一個(gè)父類 加載器。類的加載首先請(qǐng)求父類加載器加載夭苗,父類加載器無(wú)能為力時(shí)才由其子 類加載器自行加載信卡。JVM 不會(huì)向 Java 程序提供對(duì) Bootstrap 的引用。下面是關(guān) 于幾個(gè)類加載器的說(shuō)明:

  • Bootstrap:一般用本地代碼實(shí)現(xiàn)题造,負(fù)責(zé)加載 JVM 基礎(chǔ)核心類庫(kù) (rt.jar);
  • Extension:從 java.ext.dirs 系統(tǒng)屬性所指定的目錄中加載類 庫(kù)傍菇,它的父加載器是 Bootstrap;
  • System:又叫應(yīng)用類加載器,其父類是 Extension界赔。它是應(yīng)用最 廣泛的類加載器桥嗤。它從環(huán)境變量 classpath 或者系統(tǒng)屬性 java.class.path 所指定的目錄中記載類,是用戶自定義加載器 的默認(rèn)父加載器仔蝌。

15泛领、闡述 ArrayList、Vector敛惊、LinkedList 的存儲(chǔ)性能和特性渊鞋。

ArrayList 和 Vector 都是使用數(shù)組方式存儲(chǔ)數(shù)據(jù),此數(shù)組元素?cái)?shù)大于實(shí)際 存儲(chǔ)的數(shù)據(jù)以便增加和插入元素,它們都允許直接按序號(hào)索引元素锡宋,但是插入 元素要涉及數(shù)組元素移動(dòng)等內(nèi)存操作儡湾,所以索引數(shù)據(jù)快而插入數(shù)據(jù)慢,Vector中的方法由于添加了 synchronized 修飾执俩,因此 Vector 是線程安全的容器徐钠,但 性能上較 ArrayList 差,因此已經(jīng)是 Java 中的遺留容器役首。

LinkedList 使用雙 向鏈表實(shí)現(xiàn)存儲(chǔ)(將內(nèi)存中零散的內(nèi)存單元通過(guò)附加的引用關(guān)聯(lián)起來(lái)尝丐,形成一 個(gè)可以按序號(hào)索引的線性結(jié)構(gòu),這種鏈?zhǔn)酱鎯?chǔ)方式與數(shù)組的連續(xù)存儲(chǔ)方式相 比衡奥,內(nèi)存的利用率更高)爹袁,按序號(hào)索引數(shù)據(jù)需要進(jìn)行前向或后向遍歷,但是插 入數(shù)據(jù)時(shí)只需要記錄本項(xiàng)的前后項(xiàng)即可矮固,所以插入速度較快失息。

Vector 屬于遺留 容器(Java 早期的版本中提供的容器,除此之外档址,Hashtable盹兢、Dictionary、BitSet守伸、Stack蛤迎、Properties 都是遺留容器),已經(jīng)不推薦使用含友,但是由于ArrayList 和 LinkedListed 都是非線程安全的,如果遇到多個(gè)線程操作同一個(gè) 容器的場(chǎng)景校辩,則可以通過(guò)工具類 Collections 中的 synchronizedList 方法將其 轉(zhuǎn)換成線程安全的容器后再使用(這是對(duì)裝潢模式的應(yīng)用窘问,將已有對(duì)象傳入另 一個(gè)類的構(gòu)造器中創(chuàng)建新的對(duì)象來(lái)增強(qiáng)實(shí)現(xiàn))。

16宜咒、 內(nèi)存模型以及分區(qū)惠赫,需要詳細(xì)到每個(gè)區(qū)放什么?

JVM 分為堆區(qū)和棧區(qū)故黑,還有方法區(qū)儿咱,初始化的對(duì)象放在堆里面,引用放在棧里面场晶,class 類信息常量池(static 常量和 static 變量)等放在方法區(qū)new:

  • ? 方法區(qū):主要是存儲(chǔ)類信息混埠,常量池(static 常量和 static 變量),編譯后的代碼(字 節(jié)碼)等數(shù)據(jù)诗轻。
  • ? 堆:初始化的對(duì)象钳宪,成員變量 (那種非 static 的變量),所有的對(duì)象實(shí)例和數(shù)組都要 在堆上分配。
  • ? 棧:棧的結(jié)構(gòu)是棧幀組成的吏颖,調(diào)用一個(gè)方法就壓入一幀搔体,幀上面存儲(chǔ)局部變量表,操 作數(shù)棧半醉,方法出口等信息疚俱,局部變量表存放的是 8 大基礎(chǔ)類型加上一個(gè)應(yīng)用類型,所 以還是一個(gè)指向地址的指針缩多。
  • ? 本地方法棧:主要為 Native 方法服務(wù)呆奕。? 程序計(jì)數(shù)器:記錄當(dāng)前線程執(zhí)行的行號(hào)。

17瞧壮、java 中垃圾收集的方法有哪些?

1. 標(biāo)記-清除:這是垃圾收集算法中最基礎(chǔ)的登馒,根據(jù)名字就可以知道,它的思想就是標(biāo)記哪些要被 回收的對(duì)象咆槽,然后統(tǒng)一回收陈轿。這種方法很簡(jiǎn)單,但是會(huì)有兩個(gè)主要問(wèn)題:1.效率不 高秦忿,標(biāo)記和清除的效率都很低;2.會(huì)產(chǎn)生大量不連續(xù)的內(nèi)存碎片麦射,導(dǎo)致以后程序在 分配較大的對(duì)象時(shí),由于沒(méi)有充足的連續(xù)內(nèi)存而提前觸發(fā)一次 GC 動(dòng)作灯谣。

2. 復(fù)制算法:為了解決效率問(wèn)題潜秋,復(fù)制算法將可用內(nèi)存按容量劃分為相等的兩部分,然后每次只 使用其中的一塊胎许,當(dāng)一塊內(nèi)存用完時(shí)峻呛,就將還存活的對(duì)象復(fù)制到第二塊內(nèi)存上,然 后一次性清楚完第一塊內(nèi)存辜窑,再將第二塊上的對(duì)象復(fù)制到第一塊钩述。但是這種方式,內(nèi)存的代價(jià)太高穆碎,每次基本上都要浪費(fèi)一般的內(nèi)存牙勘。于是將該算法進(jìn)行了改進(jìn),內(nèi)存區(qū)域不再是按照 1:1 去劃分所禀,而是將內(nèi)存劃分為8:1:1 三部分方面,較大那份內(nèi)存交 Eden 區(qū),其余是兩塊較小的內(nèi)存區(qū)叫 Survior 區(qū)色徘。每次都會(huì)優(yōu)先使用 Eden 區(qū)恭金,若 Eden 區(qū)滿,就將對(duì)象復(fù)制到第二塊內(nèi)存區(qū)上褂策,然 后清除 Eden 區(qū)衫冻,如果此時(shí)存活的對(duì)象太多,以至于 Survivor 不夠時(shí)秽梅,會(huì)將這些對(duì) 象通過(guò)分配擔(dān)保機(jī)制復(fù)制到老年代中危彩。(java 堆又分為新生代和老年代)

3. 標(biāo)記-整理該算法主要是為了解決標(biāo)記-清除,產(chǎn)生大量?jī)?nèi)存碎片的問(wèn)題;當(dāng)對(duì)象存活率較高 時(shí),也解決了復(fù)制算法的效率問(wèn)題。它的不同之處就是在清除對(duì)象的時(shí)候現(xiàn)將可回 收對(duì)象移動(dòng)到一端,然后清除掉端邊界以外的對(duì)象丹擎,這樣就不會(huì)產(chǎn)生內(nèi)存碎片了。

4. 分代收集現(xiàn)在的虛擬機(jī)垃圾收集大多采用這種方式歇父,它根據(jù)對(duì)象的生存周期蒂培,將堆分為新生 代和老年代。在新生代中榜苫,由于對(duì)象生存期短护戳,每次回收都會(huì)有大量對(duì)象死去,那 么這時(shí)就采用復(fù)制算法垂睬。老年代里的對(duì)象存活率較高媳荒,沒(méi)有額外的空間進(jìn)行分配擔(dān) 保,所以可以使用標(biāo)記-整理 或者 標(biāo)記-清除驹饺。

18钳枕、簡(jiǎn)述 java 類加載機(jī)制?

虛擬機(jī)把描述類的數(shù)據(jù)從 Class 文件加載到內(nèi)存,并對(duì)數(shù)據(jù)進(jìn)行校驗(yàn)赏壹,解析和初始化鱼炒,最 終形成可以被虛擬機(jī)直接使用的 java 類型。

19蝌借、類加載器雙親委派模型機(jī)制?

當(dāng)一個(gè)類收到了類加載請(qǐng)求時(shí)昔瞧,不會(huì)自己先去加載這個(gè)類,而是將其委派給父類菩佑,由父類去加載自晰,如果此時(shí)父類不能加載,反饋給子類擎鸠,由子類去完成類的加載。

20缘圈、什么是類加載器劣光,類加載器有哪些?

實(shí)現(xiàn)通過(guò)類的權(quán)限定名獲取該類的二進(jìn)制字節(jié)流的代碼塊叫做類加載器。主要有一下四種類加載器:

  • 啟動(dòng)類加載器(Bootstrap ClassLoader)用來(lái)加載 java 核心類庫(kù)糟把,無(wú)法被 java 程序直接 引用绢涡。
  • 擴(kuò)展類加載器(extensions class loader):它用來(lái)加載 Java 的擴(kuò)展庫(kù)。Java 虛擬機(jī)的 實(shí)現(xiàn)會(huì)提供一個(gè)擴(kuò)展庫(kù)目錄遣疯。該類加載器在此目錄里面查找并加載 Java 類雄可。
  • 系統(tǒng)類加載器(system class loader):它根據(jù) Java 應(yīng)用的類路徑(CLASSPATH) 來(lái)加載 Java 類。一般來(lái)說(shuō),Java 應(yīng)用的類都是由它來(lái)完成加載的数苫〈鲜妫可以通過(guò)ClassLoader.getSystemClassLoader()來(lái)獲取它。
  • 用戶自定義類加載器虐急,通過(guò)繼承 java.lang.ClassLoader 類的方式實(shí)現(xiàn)箱残。

21、簡(jiǎn)述 java 內(nèi)存分配與回收策率以及 Minor GC 和Major GC

1. 對(duì)象優(yōu)先在堆的 Eden 區(qū)分配止吁。

2. 大對(duì)象直接進(jìn)入老年代.

3. 長(zhǎng)期存活的對(duì)象將直接進(jìn)入老年代被辑。

當(dāng) Eden 區(qū)沒(méi)有足夠的空間進(jìn)行分配時(shí),虛擬機(jī)會(huì)執(zhí)行一次 Minor GC.Minor Gc 通 常發(fā)生在新生代的 Eden 區(qū)敬惦,在這個(gè)區(qū)的對(duì)象生存期短盼理,往往發(fā)生 Gc 的頻率較高, 回收速度比較快;Full Gc/Major GC 發(fā)生在老年代俄删,一般情況下宏怔,觸發(fā)老年代 GC的時(shí)候不會(huì)觸發(fā) Minor GC,但是通過(guò)配置,可以在 Full GC 之前進(jìn)行一次 Minor GC 這樣可以加快老年代的回收速度抗蠢。

Java高頻面試題

分享不易举哟,如果感興趣的話,可以關(guān)注我的公眾號(hào)“碼之初”或者“ma_zhichu”迅矛,閱讀更多精品技術(shù)文章妨猩。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市秽褒,隨后出現(xiàn)的幾起案子壶硅,更是在濱河造成了極大的恐慌,老刑警劉巖销斟,帶你破解...
    沈念sama閱讀 211,265評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件庐椒,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡蚂踊,警方通過(guò)查閱死者的電腦和手機(jī)约谈,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,078評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)犁钟,“玉大人棱诱,你說(shuō)我怎么就攤上這事±远” “怎么了迈勋?”我有些...
    開(kāi)封第一講書(shū)人閱讀 156,852評(píng)論 0 347
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)醋粟。 經(jīng)常有香客問(wèn)我靡菇,道長(zhǎng)重归,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,408評(píng)論 1 283
  • 正文 為了忘掉前任厦凤,我火速辦了婚禮鼻吮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘泳唠。我一直安慰自己狈网,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,445評(píng)論 5 384
  • 文/花漫 我一把揭開(kāi)白布笨腥。 她就那樣靜靜地躺著拓哺,像睡著了一般。 火紅的嫁衣襯著肌膚如雪脖母。 梳的紋絲不亂的頭發(fā)上士鸥,一...
    開(kāi)封第一講書(shū)人閱讀 49,772評(píng)論 1 290
  • 那天,我揣著相機(jī)與錄音谆级,去河邊找鬼烤礁。 笑死,一個(gè)胖子當(dāng)著我的面吹牛肥照,可吹牛的內(nèi)容都是我干的脚仔。 我是一名探鬼主播,決...
    沈念sama閱讀 38,921評(píng)論 3 406
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼舆绎,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼鲤脏!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起吕朵,我...
    開(kāi)封第一講書(shū)人閱讀 37,688評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤猎醇,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后努溃,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體硫嘶,經(jīng)...
    沈念sama閱讀 44,130評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,467評(píng)論 2 325
  • 正文 我和宋清朗相戀三年梧税,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了沦疾。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,617評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡第队,死狀恐怖哮塞,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情斥铺,我是刑警寧澤彻桃,帶...
    沈念sama閱讀 34,276評(píng)論 4 329
  • 正文 年R本政府宣布坛善,位于F島的核電站晾蜘,受9級(jí)特大地震影響邻眷,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜剔交,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,882評(píng)論 3 312
  • 文/蒙蒙 一肆饶、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧岖常,春花似錦驯镊、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,740評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至偎快,卻和暖如春冯乘,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背晒夹。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,967評(píng)論 1 265
  • 我被黑心中介騙來(lái)泰國(guó)打工裆馒, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人丐怯。 一個(gè)月前我還...
    沈念sama閱讀 46,315評(píng)論 2 360
  • 正文 我出身青樓喷好,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親读跷。 傳聞我的和親對(duì)象是個(gè)殘疾皇子梗搅,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,486評(píng)論 2 348