針對《面試心得與總結—BAT、網易、蘑菇街》一文中出現的技術問題的收集與整理(1)

    最近,我在ImportNew網站上,看到了這篇文章,覺得總結的非常好,就默默的收藏起來了,覺得日後一定要好好整理學習一下,昨天突然發現在脈脈的行業頭條中,居然也推送了這篇文章,更加堅定了我整理的信心。

   文中答案和詳解部分過於詳細的我會附上,本人認爲寫的 比較好的鏈接,供大家參考,如果有什麼不正確的地方,還希望各位大神,在評論中給予指導,謝謝!

  J2SE基礎

  1. 九種基本數據類型的大小,以及他們的封裝類?

     Java提供了一組基本數據類型,包括  boolean, byte, char, short,  int, long, float, double, void. 

  同時,java也提供了這些類型的封裝類,分別爲 Boolean, Byte, Character, Short, Integer, Long, Float, Double, Void

    爲什麼Java會這麼做?在java中使用基本類型來存儲語言支持的基本數據類型,這裏沒有采用對象,而是使用了傳統的面向過程語言所採用的基本類在型,主要是從性能方面來考慮的:因爲即使最簡單的數學計算,使用對象來處理也會引起一些開銷,而這些開銷對於數學計算本來是毫無必要的。但是在java中,泛型類包括預定義的集合,使用的參數都是對象類型,無法直接使用這些基本數據類型,所以java又提供了這些基本類型的包裝器。

區別:1、基本數據類型只能按值傳遞,而封裝類按引用傳遞,2、基本類型在堆棧中創建;而對於對象類型,對象在堆中創建,對象的引用在堆棧中創建。基本類型由於在堆棧中,效率會比較高,但是可能會存在內存泄漏的問題。

  2.Switch能否用string做參數?

     Java 7之前,switch 只能支持 byte、short、char、int或者其對應的封裝類以及 Enum 類型。在 Java 7中,String支持被加上了。

  3.equals與==的區別?

    “==”比較的是值【變量(棧)內存中存放的對象的(堆)內存地址】

    equal用於比較兩個對象的值是否相同【不是比地址】

  【特別注意】Object類中的equals方法和“==”是一樣的,沒有區別,而String類,Integer類等等一些類,是重寫了equals方法,才使得equals和“==不同”,所以,當自己創建類時,自動繼承了Object的equals方法,要想實現不同的等於比較,必須重寫equals方法。"=="比"equal"運行速度快,因爲"=="只是比較引用.

參考鏈接:.equals與==

   4. Object有哪些公用方法?

    直接上代碼:

   

Object o = new Object();  
  
/** 
 * 比較當前對象和是否等於另一個對象,指向的對象是否相同 
 */  
System.out.println(o.equals(new Object()));  
  
/** 
 * 返回hashCode 
 */  
System.out.println(o.hashCode());  
  
/** 
 * 返回包名+類名+Integer.toHexString(hashCode()) 
 */  
System.out.println(o.toString());  
  
/** 
 * 返回class對象 
 */  
System.out.println(o.getClass());  
  
  
  
try {  
    /** 
     * 線程等待,Causes the current thread to wait until another thread invokes the notify() method or the notifyAll() method for this object. 
     */  
    o.wait();  
    o.wait(1000);  
    o.wait(1000,1000);  
} catch (InterruptedException e) {  
    e.printStackTrace();  
}  
  
  
/** 
 * notify()和notifyAll()都是Object對象用於通知處在等待該對象的線程的方法。兩者的最大區別在於: 
 * notifyAll使所有原來在該對象上等待被notify的線程統統退出wait的狀態,變成等待該對象上的鎖,一旦該對象被解鎖,他們就會去競爭。 
 * notify則文明得多他只是選擇一個wait狀態線程進行通知,並使它獲得該對象上的鎖,但不驚動其他同樣在等待被該對象notify的線程們,當第一個線程運行完畢以後釋放對象上的鎖此時如果該對象沒有再次使用notify語句,則即便該對象已經空閒,其他wait狀態等待的線程由於沒有得到該對象的通知,繼續處在wait狀態,直到這個對象發出一個notify或notifyAll,它們等待的是被notify或notifyAll,而不是鎖。 
 */  
o.notify();  
o.notifyAll(); 
    5. Java的四種引用,強弱軟虛,用到的場景。

  

強引用

最普遍的一種引用方式,如String s = "abc",變量s就是字符串“abc”的強引用,只要強引用存在,則垃圾回收器就不會回收這個對象。

軟引用(SoftReference)

用於描述還有用但非必須的對象,如果內存足夠,不回收,如果內存不足,則回收。一般用於實現內存敏感的高速緩存,軟引用可以和引用隊列ReferenceQueue聯合使用,如果軟引用的對象被垃圾回收,JVM就會把這個軟引用加入到與之關聯的引用隊列中。

弱引用(WeakReference)

弱引用和軟引用大致相同,弱引用與軟引用的區別在於:只具有弱引用的對象擁有更短暫的生命週期。在垃圾回收器線程掃描它所管轄的內存區域的過程中,一旦發現了只具有弱引用的對象,不管當前內存空間足夠與否,都會回收它的內存。

虛引用(PhantomReference)

就是形同虛設,與其他幾種引用都不同,虛引用並不會決定對象的生命週期。如果一個對象僅持有虛引用,那麼它就和沒有任何引用一樣,在任何時候都可能被垃圾回收器回收。 虛引用主要用來跟蹤對象被垃圾回收器回收的活動。
虛引用與軟引用和弱引用的一個區別在於:虛引用必須和引用隊列 (ReferenceQueue)聯合使用。當垃圾回收器準備回收一個對象時,如果發現它還有虛引用,就會在回收對象的內存之前,把這個虛引用加入到與之關聯的引用隊列中

參考鏈接:http://droidyue.com/blog/2014/10/12/understanding-weakreference-in-java/


   6. Hashcode的作用

hashCode方法的主要作用是爲了配合基於散列的集合一起正常運行,這樣的散列集合包括HashSet、HashMap以及HashTable

參考鏈接:淺談Java中的hashcode方法
   7.ArrayList、LinkedList、Vector的區別

   這三者都是實現了List接口,都擁有List接口裏面定義的方法,並且同時擁有Collection接口的方法;

        ArrayList:採用的是數組的方式進行存儲數據的,查詢和修改速度快,但是增加和刪除速度慢;線程是不同步的

        LinkedList:採用的是鏈表的方式進行存儲數據的,查詢和修改速度慢,但是增加和刪除速度快;線程是不同步的

        Vector:也採用的是數組的方式進行存儲的,Vector在java1.0以前用,但是ArrayList是在java1.2版本後使用的,線程是同步的,效率相比ArrayList來說慢一點;同時Vector查詢數據有迭代器,有枚舉,有get(int index),有indexOf(int index)四種方式,而ArrayList卻沒有枚舉

 8. String、StringBuffer與StringBuilder的區別

  1、可變與不可變

   String類中使用字符數組保存字符串,如下就是,因爲有“final”修飾符,所以可以知道string對象是不可變的。

   private final char value[];

   StringBuilder與StringBuffer都繼承自AbstractStringBuilder類,在AbstractStringBuilder中也是使用字符數組保存字符串,如下就是,可知這兩種對象都是可變的。

 char[] value;

   2、是否多線程安全

      String中的對象是不可變的,也就可以理解爲常量,顯然線程安全。  

      AbstractStringBuilder是StringBuilder與StringBuffer的公共父類,定義了一些字符串的基本操作,如expandCapacity、append、insert、indexOf等公共方法

      StringBuffer對方法加了同步鎖或者對調用的方法加了同步鎖,所以是線程安全的

      StringBuilder並沒有對方法進行加同步鎖,所以是非線程安全的

9. Map、Set、List、Queue、Stack的特點與用法

Map

Map是鍵值對,鍵Key是唯一不能重複的,一個鍵對應一個值,值可以重複。
TreeMap可以保證順序,HashMap不保證順序,即爲無序的。
Map中可以將Key和Value單獨抽取出來,其中KeySet()方法可以將所有的keys抽取正一個Set。而Values()方法可以將map中所有的values抽取成一個集合。

Set

不包含重複元素的集合,set中最多包含一個null元素
只能用Lterator實現單項遍歷,Set中沒有同步方法

List

有序的可重複集合。
可以在任意位置增加刪除元素。
用Iterator實現單向遍歷,也可用ListIterator實現雙向遍歷

Queue

Queue遵從先進先出原則。
使用時儘量避免add()和remove()方法,而是使用offer()來添加元素,使用poll()來移除元素,它的優點是可以通過返回值來判斷是否成功。
LinkedList實現了Queue接口。
Queue通常不允許插入null元素

Stack

Stack遵從後進先出原則。
Stack繼承自Vector。
它通過五個操作對類Vector進行擴展,允許將向量視爲堆棧,它提供了通常的push和pop操作,以及取堆棧頂點的peek()方法、測試堆棧是否爲空的empty方法等

如果涉及堆棧,隊列等操作,建議使用List
對於快速插入和刪除元素的,建議使用LinkedList
如果需要快速隨機訪問元素的,建議使用ArrayList

HashMap和Hashtable都實現了Map接口,但決定用哪一個之前先要弄清楚它們之間的分別。主要的區別有:線程安全性,同步(synchronization),以及速度。

10. HashMap和HashTable的區別。

  1. HashMap幾乎可以等價於Hashtable,除了HashMap是非synchronized的,並可以接受null(HashMap可以接受爲null的鍵值(key)和值(value),而Hashtable則不行)。
  2. HashMap是非synchronized,而Hashtable是synchronized,這意味着Hashtable是線程安全的,多個線程可以共享一個Hashtable;而如果沒有正確的同步的話,多個線程是不能共享HashMap的。Java 5提供了ConcurrentHashMap,它是HashTable的替代,比HashTable的擴展性更好。
  3. 另一個區別是HashMap的迭代器(Iterator)是fail-fast迭代器,而Hashtable的enumerator迭代器不是fail-fast的。所以當有其它線程改變了HashMap的結構(增加或者移除元素),將會拋出ConcurrentModificationException,但迭代器本身的remove()方法移除元素則不會拋出ConcurrentModificationException異常。但這並不是一個一定發生的行爲,要看JVM。這條同樣也是Enumeration和Iterator的區別。
  4. 由於Hashtable是線程安全的也是synchronized,所以在單線程環境下它比HashMap要慢。如果你不需要同步,只需要單一線程,那麼使用HashMap性能要好過Hashtable。
  5. HashMap不能保證隨着時間的推移Map中的元素次序是不變的
參考文章:HashMap和HashTable的區別

11、HashMap和ConcurrentHashMap的區別,HashMap的底層源碼。

Hashmap本質是數組加鏈表。根據key取得hash值,然後計算出數組下標,如果多個key對應到同一個下標,就用鏈表串起來,新插入的在前面。

ConcurrentHashMap:在hashMap的基礎上,ConcurrentHashMap將數據分爲多個segment(類似hashtable),默認16個(concurrency level),然後在每一個分段上都用鎖進行保護,從而讓鎖的粒度更精細一些,併發性能更好


參考文章:HashMap VS ConcurrentHashMap


HashMap的源碼
:【Java集合源碼剖析】HashMap源碼剖析

12、TreeMap、HashMap、LindedHashMap的區別

1.HashMap裏面存入的鍵值對在取出的時候是隨機的,也是我們最常用的一個Map.它根據鍵的HashCode值存儲數據,根據鍵可以直接獲取它的值,具有很快的訪問速度。在Map 中插入、刪除和定位元素,HashMap 是最好的選擇。  
2.TreeMap取出來的是排序後的鍵值對。但如果您要按自然順序或自定義順序遍歷鍵,那麼TreeMap會更好。  
3. LinkedHashMap 是HashMap的一個子類,如果需要輸出的順序和輸入的相同,那麼用LinkedHashMap可以實現.  (應用場景:購物車等需要順序的)
13. Collection包結構,與Collections的區別。

Collection是集合類的上級接口,子接口主要有Set 和List、Map。 

Collections是針對集合類的一個幫助類,提供了操作集合的工具方法:一系列靜態方法實現對各種集合的搜索、排序、線程安全化等操作。

給大家補充一個鏈接:collections在java中的常見用法


參考鏈接:http://blog.sina.com.cn/s/blog_105817120102vzh6.html


14、try catch finally,try裏有return,finally還執行麼?

   1、不管有木有出現異常,finally塊中代碼都會執行;
2、當try和catch中有return時,finally仍然會執行;
3、finally是在return後面的表達式運算後執行的(此時並沒有返回運算後的值,而是先把要返回的值保存起來,管finally中的代碼怎麼樣,返回的值都不會改變,任然是之前保存的值),所以函數返回值是在finally執行前確定的;
4、finally中最好不要包含return,否則程序會提前退出,返回值不是try或catch中保存的返回值。

情況1:try{} catch(){}finally{} return;
            顯然程序按順序執行。
情況2:try{ return; }catch(){} finally{} return;
          程序執行try塊中return之前(包括return語句中的表達式運算)代碼;
         再執行finally塊,最後執行try中return;
         finally塊之後的語句return,因爲程序在try中已經return所以不再執行。
情況3:try{ } catch(){return;} finally{} return;
         程序先執行try,如果遇到異常執行catch塊,
         有異常:則執行catch中return之前(包括return語句中的表達式運算)代碼,再執行finally語句中全部代碼,
                     最後執行catch塊中return. finally之後也就是4處的代碼不再執行。
         無異常:執行完try再finally再return.
情況4:try{ return; }catch(){} finally{return;}
          程序執行try塊中return之前(包括return語句中的表達式運算)代碼;
          再執行finally塊,因爲finally塊中有return所以提前退出。
情況5:try{} catch(){return;}finally{return;}
          程序執行catch塊中return之前(包括return語句中的表達式運算)代碼;
          再執行finally塊,因爲finally塊中有return所以提前退出。
情況6:try{ return;}catch(){return;} finally{return;}
          程序執行try塊中return之前(包括return語句中的表達式運算)代碼;
          有異常:執行catch塊中return之前(包括return語句中的表達式運算)代碼;
                       則再執行finally塊,因爲finally塊中有return所以提前退出。
          無異常:則再執行finally塊,因爲finally塊中有return所以提前退出。

最終結論:任何執行try 或者catch中的return語句之前,都會先執行finally語句,如果finally存在的話。
                  如果finally中有return語句,那麼程序就return了,所以finally中的return是一定會被return的,
                  編譯器把finally中的return實現爲一個warning。

15. Excption與Error包結構。OOM你遇到過哪些情況,SOF你遇到過哪些情況

這裏寫圖片描述

(一)Throwable

  Throwable 類是 Java 語言中所有錯誤或異常的超類。只有當對象是此類或其子類之一的實例時,才能通過 Java 虛擬機或者 Java throw 語句拋出,纔可以是 catch 子句中的參數類型。
  Throwable 類及其子類有兩個構造方法,一個不帶參數,另一個帶有 String 參數,此參數可用於生成詳細消息。
  Throwable 包含了其線程創建時線程執行堆棧的快照。它還包含了給出有關錯誤更多信息的消息字符串

  
Java將可拋出(Throwable)的結構分爲三種類型:
  錯誤(Error)
  運行時異常(RuntimeException)
  被檢查的異常(Checked Exception)

 1.Error
  Error 是 Throwable 的子類,用於指示合理的應用程序不應該試圖捕獲的嚴重問題。大多數這樣的錯誤都是異常條件。
  和RuntimeException一樣, 編譯器也不會檢查Error。
  當資源不足、約束失敗、或是其它程序無法繼續運行的條件發生時,就產生錯誤,程序本身無法修復這些錯誤的。
  
 2.Exception
  Exception 類及其子類是 Throwable 的一種形式,它指出了合理的應用程序想要捕獲的條件。
   對於可以恢復的條件使用被檢查異常(Exception的子類中除了RuntimeException之外的其它子類),對於程序錯誤使用運行時異常。 
  

① ClassNotFoundException
  
當應用程序試圖使用以下方法通過字符串名加載類時:
Class 類中的 forName 方法。
ClassLoader 類中的 findSystemClass 方法。
ClassLoader 類中的 loadClass 方法。
但是沒有找到具有指定名稱的類的定義,拋出該異常。

?
1
2
3
4
<code>② CloneNotSupportedException
 
當調用 Object 類中的 clone 方法複製對象,但該對象的類無法實現 Cloneable 接口時,拋出該異常。重寫 clone 方法的應用程序也可能拋出此異常,指示不能或不應複製一個對象。
</code>

③ IOException
當發生某種 I/O 異常時,拋出此異常。此類是失敗或中斷的 I/O 操作生成的異常的通用類。

-EOFException
  當輸入過程中意外到達文件或流的末尾時,拋出此異常。
此異常主要被數據輸入流用來表明到達流的末尾。
注意:其他許多輸入操作返回一個特殊值表示到達流的末尾,而不是拋出異常。
    
-FileNotFoundException
  當試圖打開指定路徑名錶示的文件失敗時,拋出此異常。
在不存在具有指定路徑名的文件時,此異常將由 FileInputStream、FileOutputStream 和 RandomAccessFile 構造方法拋出。如果該文件存在,但是由於某些原因不可訪問,比如試圖打開一個只讀文件進行寫入,則此時這些構造方法仍然會拋出該異常。

-MalformedURLException
  拋出這一異常指示出現了錯誤的 URL。或者在規範字符串中找不到任何合法協議,或者無法解析字符串。 
 
-UnknownHostException
  指示主機 IP 地址無法確定而拋出的異常。

④ RuntimeException
   是那些可能在 Java 虛擬機正常運行期間拋出的異常的超類。可能在執行方法期間拋出但未被捕獲的 RuntimeException 的任何子類都無需在 throws 子句中進行聲明。
   Java編譯器不會檢查它。當程序中可能出現這類異常時,還是會編譯通過。
   雖然Java編譯器不會檢查運行時異常,但是我們也可以通過throws進行聲明拋出,也可以通過try-catch對它進行捕獲處理。

-ArithmeticException
當出現異常的運算條件時,拋出此異常。例如,一個整數“除以零”時,拋出此類的一個實例。

-ClassCastException
  當試圖將對象強制轉換爲不是實例的子類時,拋出該異常。
例如:Object x = new Integer(0);

-LllegalArgumentException
  拋出的異常表明向方法傳遞了一個不合法或不正確的參數。

-IllegalStateException
  在非法或不適當的時間調用方法時產生的信號。換句話說,即 Java 環境或 Java 應用程序沒有處於請求操作所要求的適當狀態下。

-IndexOutOfBoundsException 
  指示某排序索引(例如對數組、字符串或向量的排序)超出範圍時拋出。
應用程序可以爲這個類創建子類,以指示類似的異常。

-NoSuchElementException
  由 Enumeration 的 nextElement 方法拋出,表明枚舉中沒有更多的元素。

-NullPointerException
  當應用程序試圖在需要對象的地方使用 null 時,拋出該異常。這種情況包括:
調用 null 對象的實例方法。
訪問或修改 null 對象的字段。
將 null 作爲一個數組,獲得其長度。
將 null 作爲一個數組,訪問或修改其時間片。
將 null 作爲 Throwable 值拋出。
應用程序應該拋出該類的實例,指示其他對 null 對象的非法使用。

(二) SOF (堆棧溢出 StackOverflow)

StackOverflowError 的定義:
當應用程序遞歸太深而發生堆棧溢出時,拋出該錯誤。

因爲棧一般默認爲1-2m,一旦出現死循環或者是大量的遞歸調用,在不斷的壓棧過程中,造成棧容量超過1m而導致溢出。

棧溢出的原因:

   

<code>遞歸調用
 
大量循環或死循環
 
全局變量是否過多
 
數組、List、map數據過大
</code>

   

  

   
   
   

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章