有了這些面試寶典,還怕拿不到大廠offer?BATJava面試真題分享

BAT面試真題分享(Java崗位)

有了這些面試寶典,還怕拿不到大廠offer?BATJava面試真題分享

1. 重要性:在Java語言中, abstract class 和interface 是支持抽象類定義的兩種機制。正是由於這兩種機制的存在,才賦予了Java強大的 面向對象能力。

2. 簡單、規範性:如果一個項目比較龐大,那麼就需要一個能理清所有業務的架構師來定義一些主要的接口,這些接口不僅告訴開發人員你需要實現那些業務,而且也將命名規範限制住了(防止一些開發人員隨便命名導致別的程序員無法看明白)。

3. 維護、拓展性:比如有一個類,實現了某個功能,突然有一天,發現這個類滿足不了需求了,然後又要重新設計這個類,更糟糕是你可能要放棄這個類,那麼其他地方可能有引用他,這樣修改起來很麻煩。

如果一開始定義一個接口,把功能放在接口裡,然後定義類時實現這個接口,然後只要用這個接口去引用實現它的類就行了,以後要換的話只不過是引用另一個類而已,這樣就達到維護、拓展的方便性。比如有個method1的方法,如果用接口,【接口名】 【對象名】=new 【實現接口的類】,這樣想用哪個類的對象就可以new哪個對象了,new a();就是用a的方法,new b()就是用b的方法,就和USB接口一樣,插什麼讀什麼,就是這個原理。

你要做一個畫板程序,其中裡面有一個面板類,主要負責繪畫功能,然後你就這樣定義了這個類。

4. 安全、嚴密性:接口是實現軟件松耦合的重要手段,它描敘了系統對外的所有服務,而不涉及任何具體的實現細節。這樣就比較安全、嚴密一些(一般軟件服務商考慮的比較多,jdk中很多方法就是實現了某個接口)。

  • 為子類提供一個公共的類型;
  • 封裝子類中重複內容(成員變量和方法);
  • 定義有抽象方法,子類雖然有不同的實現,但該方法的定義是一致的

三. 內部類的作用-(樂視面試題)

  • 內部類可以很好的實現隱藏, 一般的非內部類,是不允許有 private 與protected權限的,但內部類可以
  • 內部類擁有外圍類的所有元素的訪問權限
  • 可以實現多重繼承
  • 可以避免修改接口而實現同一個類中兩種同名方法的調用。

四. Java 虛擬機的特性-百度-(樂視面試題)

1. 移植性

無論是GC還是Hotspot都可以用在任何Java可用的地方。比方說,JRuby可以運行在其他平臺上,Rails應用就可以運行在IBM主機上的JRuby上,而且這臺IBM主機運行的是CP/CMS。實際上,由於Java和OpenJDK項目的開源,我們正在看到越來越多的平臺的衍生,因此JVM的移植性也將越來越棒。

2. 成熟

JVM已有超過15年的歷史,在過去的這些年裡,許多開發者為它做出了許多貢獻,使得它的性能一次又一次地提升,讓JVM變得更加穩定、快速和廣泛。

3. 覆蓋面

JRuby和JVM上的其他語言項目已經被開發者所承認,一個典型的例子是invokedynamic specification (aka JSR292)。JSR越來越配合新的語言,JVM已不再是Java一個人定製規則。JVM正在構建成為類如JRuby等項目的優良平臺。

五. 哪些情況下的對象會被垃圾回收機制處理掉-(美團-小米麵試題)

  • 所有實例都沒有活動線程訪問。
  • 沒有被其他任何實例訪問的循環引用實例。
  • Java 中有不同的引用類型。判斷實例是否符合垃圾收集的條件都依賴於它的引用類型
有了這些面試寶典,還怕拿不到大廠offer?BATJava面試真題分享

六. 進程和線程的區別-(獵豹-美團面試題)

簡而言之,一個程序至少有一個進程,一個進程至少有一個線程.

線程的劃分尺度小於進程,使得多線程程序的併發性高。

另外,進程在執行過程中擁有獨立的內存單元,而多個線程共享內存,從而極大地提高了程序的運行效率。

線程在執行過程中與進程還是有區別的。每個獨立的線程有一個程序運行的入口、順序執行序列和程序的出口。但是線程不能夠獨立執行,必須依存在應用程序中,由應用程序提供多個線程執行控制。

從邏輯角度來看,多線程的意義在於一個應用程序中,有多個執行部分可以同時執行。但操作系統並沒有將多個線程看做多個獨立的應用,來實現進程的調度和管理以及資源分配。這就是進程和線程的重要區別。

進程是具有一定獨立功能的程序關於某個數據集合上的一次運行活動,進程是系統進行資源分配和調度的一個獨立單位.

線程是進程的一個實體,是CPU調度和分派的基本單位,它是比進程更小的能獨立運行的基本單位.線程自己基本上不擁有系統資源,只擁有一點在運行中必不可少的資源(如程序計數器,一組寄存器和棧),但是它可與同屬一個進程的其他的線程共享進程所擁有的全部資源.

一個線程可以創建和撤銷另一個線程;同一個進程中的多個線程之間可以併發執行.

七. java中==和equals和hashCode的區別-(樂視面試題)

== :該操作符生成的是一個boolean結果,它計算的是操作數的值之間的關係

equals :Object 的 實例方法,比較兩個對象的content是否相同

hashCode :Object 的 native方法 , 獲取對象的哈希值,用於確定該對象在哈希表中的索引位置,它實際上是一個int型整數

equals方法是基類Object中的實例方法,因此對所有繼承於Object的類都會有該方法

先比較引用是否相同(是否為同一對象),

再判斷類型是否一致(是否為同一類型),

最後比較內容是否一致

八. HashMap的實現原理-(美團面試題)

  • 先對table的非空檢查,為空就初始化
  • 對key的非空檢查,如果key是null,會被存儲到table[0],因為null的hash值總是0
  • 對key的hashCode()做hash,然後再通過indexFor()計算index,這個就是table數組的索引;
  • 如果在剛才計算出來的索引位置中table沒有元素,直接把Entry對象放在那個索引上
  • 如果索引上有元素,然後會進行迭代,在迭代的過程中,會調用equals()方法來檢查key的相等性(key.equals(k)),如果這個方法返回true,它就會用當前Entry的value來替換之前的value。如果返回false就一直到Entry->next是null,把當前的Entry對象變成鏈表的下一個節點
  • 如果table的長度超過了loadFactor *current capacity,就要重新resize一個原來長度兩倍的HashMap
  • 對key進行null檢查。如果key是null,table[0]這個位置的元素將被返回。
  • key的hashcode()方法被調用,然後計算hash值。
  • indexFor(hash,table.length)用來計算要獲取的Entry對象在table數組中的精確的位置,使用剛才計算的hash值。在獲取了table數組的索引之後,會迭代鏈表,調用equals()方法檢查key的相等性,如果equals()方法返回true,get方法返回Entry對象的value,否則,返回null。
  • HashMap中數據是用一個叫table的數組來存的,table的索引在邏輯上叫做“桶”(bucket),它存儲了鏈表的第一個元素。
  • HashMap有一個叫做Entry的內部類,它用來存儲key-value對。table數組存的就是它。Entry用一個next屬性實現多個Entry以單向鏈表存放,插入元素時,如果兩條Key落在同一個桶,並且這兩條key不equals,後入桶的Entry將next指向桶當前的Entry,否則後入桶的會將前面的給覆蓋(確保key的唯一性);
  • 使用HashMap的時候最好使用泛型,如果key放的是自己的對象,最好重寫equals()和hashcode()。

哈希表是一個數組+鏈表的存儲結構。HashMap存儲結構文字解釋:

<code> table[0] →[index=1,Entry] 
table[1] →[index=2,Entry]
...
依次類推
/<code>

九. string-stringbuffer-stringbuilder區別-(小米-樂視-百度面試題)

  • String 字符串常量
  • StringBuffer 字符串變量(線程安全)
  • StringBuilder 字符串變量(非線程安全)

String 類型和 StringBuffer 類型的主要性能區別其實在於 String 是不可變的對象, 因此在每次對 String 類型進行改變的時候其實都等同於生成了一個新的 String 對象,然後將指針指向新的 String 對象,所以經常改變內容的字符串最好不要用 String ,因為每次生成對象都會對系統性能產生影響,特別當內存中無引用對象多了以後, JVM 的 GC 就會開始工作,那速度是一定會相當慢的

StringBuffer 類則結果就不一樣了,每次結果都會對 StringBuffer 對象本身進行操作,而不是生成新的對象,再改變對象引用。所以在一般情況下我們推薦使用 StringBuffer ,特別是字符串對象經常改變的情況下。而在某些特別情況下, String 對象的字符串拼接其實是被 JVM 解釋成了 StringBuffer 對象的拼接,所以這些時候 String 對象的速度並不會比 StringBuffer 對象慢,而特別是以下的字符串對象生成中, String 效率是遠要比 StringBuffer 快的:

java.lang.StringBuilder一個可變的字符序列是5.0新增的。此類提供一個與 StringBuffer 兼容的 API,但不保證同步。該類被設計用作 StringBuffer 的一個簡易替換,用在字符串緩衝區被單個線程使用的時候(這種情況很普遍)。如果可能,建議優先採用該類,因為在大多數實現中,它比 StringBuffer 要快。兩者的方法基本相同

十. 什麼導致線程阻塞-58-美團

  • 線程執行了Thread.sleep(int n)方法,線程放棄CPU,睡眠n毫秒,然後恢復運行。
  • 線程要執行一段同步代碼,由於無法獲得相關的同步鎖,只好進入阻塞狀態,等到獲得了同步鎖,才能恢復運行。
  • 線程執行了一個對象的wait()方法,進入阻塞狀態,只有等到其他線程執行了該對象的notify()或notifyAll()方法,才可能將其喚醒。
  • 線程執行I/O操作或進行遠程通信時,會因為等待相關的資源而進入阻塞狀態。例如,當線程執行System.in.read()方法時,如果用戶沒有向控制檯輸入數據,則該線程會一直等讀到了用戶的輸入數據才從read()方法返回。進行遠程通信時,在客戶程序中,線程在以下情況可能進入阻塞狀態。
  • 請求與服務器建立連接時,即當線程執行Socket的帶參數的構造方法,或執行Socket的connect()方法時,會進入阻塞狀態,直到連接成功,此線程才從Socket的構造方法或connect()方法返回。
  • 線程從Socket的輸入流讀取數據時,如果沒有足夠的數據,就會進入阻塞狀態,直到讀到了足夠的數據,或者到達輸入流的末尾,或者出現了異常,才從輸入流的read()方法返回或異常中斷。輸入流中有多少數據才算足夠呢?這要看線程執行的read()方法的類型。int read(); 只要輸入流中有一個字節,就算足夠。int read(byte[] buff); 只要輸入流中的字節數目與參數buff數組的長度相同,就算足夠。String readLine(); 只要輸入流中郵一行字符串,就算足夠。值得注意的是,InputStream類並沒有readLine方法,在過濾流BufferedReader類中才有此方法。
  • 線程向Socket的輸出流寫一批數據時,可能會進入阻塞狀態,等到輸出了所有的數據,或者出現異常,才從輸出流的write()方法返回或異常中斷。
  • 調用Socket的setSoLinger()方法設置了關閉Socket的延遲時間,那麼當線程執行Socket的close方法時,會進入阻塞狀態,直到底層Socket發送完所有剩餘數據,或者超過了setSoLinger()方法設置的延遲時間,才從close()方法返回。
有了這些面試寶典,還怕拿不到大廠offer?BATJava面試真題分享

十一. 多線程同步機制-(獵豹面試題)

volatile和synchronized的區別

  • volatile通過變量的可見性,指定線程必須從主存中讀取變量的最新值;synchronized通過阻塞線程的方式,只有當前線程能訪問該變量,鎖定了當前變量。
  • volatile使用在變量級別;synchronized可以使用在變量、方法、類級別
  • volatile不會造成線程阻塞;synchronized可能會造成線程阻塞
  • volatile不能保證原子性;synchronized能保證原子性
  • volatile標記的變量不會被編譯器優化;synchronized標記的變量有可能會被編譯器優化(指令重排)

十二. ArrayMap對比HashMap

如果hashmap和Arraymap在內存優化方面,肯定會選擇ArrayMap,因為ArrayMap佔用空間小,但是ArrayMap以時間換空間,速度也是慢了很多。

HashMap內部有一個HashMapEntry[]對象,每一個鍵值對都存儲在這個對象裡,當使用put方法添加鍵值對時,就會new一個HashMapEntry對象

ArrayMap的存儲中沒有Entry這個東西,他是由兩個數組來維護的,mHashes數組中保存的是每一項的HashCode值,mArray中就是鍵值對,每兩個元素代表一個鍵值對,前面保存key,後面的保存value

添加數據時擴容時的處理不一樣

HashMap 是創建一個新的容量是之前二倍的對象,然後將之前的數據移動到新的。

ArrayMap用的是copy數據,所以效率相對要高,ArrayMap提供了數組收縮的功能,在clear或remove後,會重新收縮數組,是否空間,

十三. hashmap和hashtable的區別-(樂視-小米-360面試題)

HashMap 不是線程安全的

HashMap 是 map 接口的實現類,是將鍵映射到值的對象,其中鍵和值都是對象,並且不能包含重複鍵,但可以包含重複值。HashMap 允許 null key 和 null value,而 HashTable 不允許。

HashTable 是線程安全 Collection。

HashMap 是 HashTable 的輕量級實現,他們都完成了Map 接口,主要區別在於 HashMap 允許 null key 和 null value,由於非線程安全,效率上可能高於 Hashtable。

區別如下:

  • HashMap允許將 null 作為一個 entry 的 key 或者 value,而 Hashtable 不允許。
  • HashMap 把 Hashtable 的 contains 方法去掉了,改成 containsValue 和 containsKey。因為 contains 方法容易讓人引起誤解。
  • HashTable 繼承自 Dictionary 類,而 HashMap 是 Java1.2 引進的 Map interface 的一個實現。
  • HashTable 的方法是 Synchronize 的,而 HashMap 不是,在多個線程訪問 Hashtable 時,不需要自己為它的方法實現同步,而 HashMap 就必須為之提供外同步。
  • Hashtable 和 HashMap 採用的 hash/rehash 算法都大概一樣,所以性能不會有很大的差異

BAT大廠Java崗面試寶典分享"關注+轉發,私信我【888】"即可免費獲取!


有了這些面試寶典,還怕拿不到大廠offer?BATJava面試真題分享


有了這些面試寶典,還怕拿不到大廠offer?BATJava面試真題分享


分享到:


相關文章: