最近面試的小夥伴不少,對此我整理了一份Java面試題手冊:基礎知識、JavaOOP、Java集合/泛型面試題、Java異常面試題、Java中的IO與NIO面試題、Java反射、Java序列化、Java註解、多線程&併發、JVM、Mysql、Redis、Memcached、MongoDB、Spring、SpringBoot、SpringCloud、RabbitMQ、Dubbo、MyBatis、ZooKeeper、數據結構、算法、Elasticsearch、Kafka、微服務、Linux等等。
能夠分享給你們學習。【持續更新中】java
完整版Java面試題地址:【2021最新版】Java面試真題彙總mysql
序號 | 內容 | 地址連接 |
---|---|---|
1 | 【2021最新版】JavaOOP面試題總結 | http://www.noobyard.com/article/p-rncfmibs-oe.html |
2 | 【2021最新版】多線程&併發面試題總結 | 未更新 |
3 | 【2021最新版】JVM面試題總結 | 未更新 |
4 | 【2021最新版】Mysql面試題總結 | 未更新 |
5 | 【2021最新版】Redis面試題總結 | 未更新 |
6 | 【2021最新版】Memcached面試題總結 | 未更新 |
7 | 【2021最新版】MongoDB面試題總結 | 未更新 |
8 | 【2021最新版】Spring面試題總結 | 未更新 |
9 | 【2021最新版】Spring Boot面試題總結 | 未更新 |
10 | 【2021最新版】Spring Cloud面試題總結 | 未更新 |
11 | 【2021最新版】RabbitMQ面試題總結 | 未更新 |
12 | 【2021最新版】Dubbo面試題總結 | 未更新 |
13 | 【2021最新版】MyBatis面試題總結 | 未更新 |
14 | 【2021最新版】ZooKeeper面試題總結 | 未更新 |
15 | 【2021最新版】數據結構面試題總結 | 未更新 |
16 | 【2021最新版】算法面試題總結 | 未更新 |
17 | 【2021最新版】Elasticsearch面試題總結 | 未更新 |
18 | 【2021最新版】Kafka面試題總結 | 未更新 |
19 | 【2021最新版】微服務面試題總結 | 未更新 |
20 | 【2021最新版】Linux面試題總結 | 未更新 |
答: Array(數組)是基於索引(index)的數據結構,它使用索引在數組中搜索和讀取數據是很快的。web
Array獲取數據的時間複雜度是O(1),可是要刪除數據倒是開銷很大,由於這須要重排數組中的全部數據,(由於刪除數據之後,須要把後面全部的數據前移)面試
缺點:數組初始化必須指定初始化的長度,不然報錯。算法
例如:sql
int[] a = new int[4];//推薦使用int[] 這種方式初始化 int c[] = { 23,43,56,78};//長度:4,索引範圍:[0,3]
List—是一個有序的集合,能夠包含重複的元素,提供了按索引訪問的方式,它繼承Collection。數組
List有兩個重要的實現類:ArrayList和LinkedList。安全
ArrayList:能夠看做是可以自動增加容量的數組。網絡
ArrayList的toArray方法返回一個數組。數據結構
ArrayList的asList方法返回一個列表。
ArrayList底層的實現是Array,數組擴容實現。
LinkList是一個雙鏈表,在添加和刪除元素時具備比ArrayList更好的性能,但在get與set方面弱於ArrayList。固然,這些對比都是指數據量很大或者操做很頻繁。
答:
一、二者父類不一樣
HashMap是繼承自AbstractMap類,而Hashtable是繼承自Dictionary類。不過它們都實現了同時實現了map、Cloneable(可複製)、Serializable(可序列化)這三個接口。
二、對外提供的接口不一樣
Hashtable比HashMap多提供了elments() 和contains() 兩個方法。elments() 方法繼承自Hashtable的父類Dictionnary。elements() 方法用於返回此Hashtable中的value的枚舉。
contains()方法判斷該Hashtable是否包含傳入的value。它的做用與containsValue()一致。事實上,contansValue() 就只是調用了一下contains() 方法。
三、對null的支持不一樣
Hashtable:key和value都不能爲null。
HashMap:key能夠爲null,可是這樣的key只能有一個,由於必須保證key的惟一性;能夠有多個key
值對應的value爲null。
四、安全性不一樣
HashMap是線程不安全的,在多線程併發的環境下,可能會產生死鎖等問題,所以須要開發人員本身處理多線程的安全問題。
Hashtable是線程安全的,它的每一個方法上都有synchronized 關鍵字,所以可直接用於多線程中。
雖然HashMap是線程不安全的,可是它的效率遠遠高於Hashtable,這樣設計是合理的,由於大部分的使用場景都是單線程。當須要多線程操做的時候可使用線程安全的ConcurrentHashMap。
ConcurrentHashMap雖然也是線程安全的,可是它的效率比Hashtable要高好多倍。由於ConcurrentHashMap使用了分段鎖,並不對整個數據進行鎖定。
五、初始容量大小和每次擴充容量大小不一樣
六、計算hash值的方法不一樣
答:
泛型是Java SE 1.5以後的特性, 《Java 核心技術》中對泛型的定義是:
「泛型」 意味着編寫的代碼能夠被不一樣類型的對象所重用。
「泛型」,顧名思義,「泛指的類型」。咱們提供了泛指的概念,但具體執行的時候卻能夠有具體的規則來約束,好比咱們用的很是多的ArrayList就是個泛型類,ArrayList做爲集合能夠存放各類元素,如
Integer, String,自定義的各類類型等,但在咱們使用的時候經過具體的規則來約束,如咱們能夠約束集合中只存放Integer類型的元素,如:
List<Integer> iniData = new ArrayList<>()
使用泛型的好處?
以集合來舉例,使用泛型的好處是咱們沒必要由於添加元素類型的不一樣而定義不一樣類型的集合。
如:整型集合類,浮點型集合類,字符串集合類。
咱們能夠定義一個集合來存放整型、浮點型,字符串型數據,而這並非最重要的,由於咱們只要把底層存儲設置了Object便可,添加的數據所有均可向上轉型爲Object。
更重要的是咱們能夠經過規則按照本身的想法控制存儲的數據類型。
答:
主要包含set(集)、 list(列表包含 Queue)和 map(映射)。
Collection: Collection 是集合 List、 Set、 Queue 的最基本的接口。
Iterator:迭代器,能夠經過迭代器遍歷集合中的數據
Map:是映射表的基礎接口
答:
分別是 ArrayList、 Vector 和LinkedList 。
List接口結構圖
答:
同) 而是按照哈希值來存的因此取數據也是按照哈希值取得。元素的哈希值是經過元素的hashcode 方法來獲取的, HashSet 首先判斷兩個元素的哈希值,若是哈希值同樣,接着會比較equals 方法 若是 equls 結果爲 true , HashSet 就視爲同一個元素。若是 equals 爲 false 就不是同一個元素。
哈希值相同 equals 爲 false 的元素是怎麼存儲呢,就是在一樣的哈希值下順延(能夠認爲哈希值相同的元素放在一個哈希桶中)。也就是哈希同樣的存一列。
如圖 1 表示 hashCode 值不相同的狀況; 圖 2 表示 hashCode 值相同,但 equals 不相同的狀況。
HashSet 經過 hashCode 值來肯定元素在內存中的位置。 一個 hashCode 位置上能夠存放多個元素。
答:
HashMap 根據鍵的 hashCode 值存儲數據,大多數狀況下能夠直接定位到它的值,於是具備很快的訪問速度,但遍歷順序倒是不肯定的。 HashMap 最多隻容許一條記錄的鍵爲 null,容許多條記錄的值爲 null。 HashMap 非線程安全,即任一時刻能夠有多個線程同時寫 HashMap,可能會致使數據的不一致。若是須要知足線程安全,能夠用 Collections 的 synchronizedMap 方法使HashMap 具備線程安全的能力,或者使用 ConcurrentHashMap。 咱們用下面這張圖來介紹HashMap 的結構。
大方向上,HashMap裏面是一個數組,而後數組中每一個元素是一個單向鏈表。上圖中,每一個綠色的實體是嵌套類Entry的實例,Entry包含四個屬性:key、value、hash值和用於單向鏈表的next。
capacity:當前數組容量,始終保持 2^n,能夠擴容,擴容後數組大小爲當前的2倍。
oadFactor:負載因子,默認爲0.75。
threshold:擴容的閾值,等於capacity * loadFactor。
Java8對HashMap進行了一些修改, 最大的不一樣就是利用了紅黑樹,因此其由 數組+鏈表+紅黑樹 組成。
根據Java7HashMap的介紹,咱們知道,查找的時候,根據hash值咱們可以快速定位到數組的具體下標,可是以後的話,須要順着鏈表一個個比較下去才能找到咱們須要的,時間複雜度取決鏈表的長度,爲O(n)。爲了下降這部分的開銷,在Java8中, 當鏈表中的元素超過了8個之後,會將鏈表轉換爲紅黑樹,在這些位置進行查找的時候能夠下降時間複雜度爲O(logN)。
答:
泛型類的聲明和非泛型類的聲明相似,除了在類名後面添加了類型參數聲明部分。和泛型方法同樣,泛型類的類型參數聲明部分也包含一個或多個類型參數,參數間用逗號隔開。一個泛型參數,也被稱爲一個類型變量,是用於指定一個泛型類型名稱的標識符。由於他們接受一個或多個參數,這些類被稱爲參數化的類或參數化的類型。
public class Box<T> { private T t; public void add(T t) { this.t = t; } public T get() { return t; } }
答:
1.編譯時異常。
2.運行時異常。
答:
1.Error和Exception都是java錯誤處理機制的一部分,都繼承了Throwable類。
2.Exception表示的異常,異常能夠經過程序來捕捉,或者優化程序來避免。
3.Error表示的是系統錯誤,不能經過程序來進行錯誤處理。
答:
error表示恢復不是不可能但很困難的狀況下的一種嚴重問題。好比說內存溢出。不可能期望程序能處理這樣的狀況exception 表示一種設計或實現問題。也就是說,它表示若是程序運行正常,從不會發生的狀況
答:
File FileInputSteam,FileOutputStream
BufferInputStream,BufferedOutputSream PrintWrite FileReader,FileWriter
BufferReader,BufferedWriter ObjectInputStream,ObjectOutputSream
答:
當用戶線程發起一個read操做後,並不須要等待,而是立刻就獲得了一個結果。 若是結果是一個error時,它就知道數據尚未準備好,因而它能夠再次發送read操做。一旦內核中的數據準備好了,而且又再次收到了用戶線程的請求,那麼它立刻就將數據拷貝到了用戶線程,而後返回。因此事實上,在非阻塞IO模型中,用戶線程須要不斷地詢問內核數據是否就緒,也就說非阻塞IO不會交出CPU,而會一直佔用CPU。
典型的非阻塞IO模型通常以下:
while(true){ data = socket.read(); if(data!= error){ //處理數據 break; } }
可是對於非阻塞IO就有一個很是嚴重的問題, 在while循環中須要不斷地去詢問內核數據是否就緒,這樣會致使CPU佔用率很是高,所以通常狀況下不多使用while循環這種方式來讀取數據。
答:
Buffer,故名思意, 緩衝區,其實是一個容器,是一個連續數組。 Channel提供從文件、網絡讀取數據的渠道,可是讀取或寫入的數據都必須經由Buffer。
上面的圖描述了從一個客戶端向服務端發送數據,而後服務端接收數據的過程。客戶端發送數據時,必須先將數據存入Buffer 中,而後將Buffer中的內容寫入通道。服務端這邊接收數據必須經過Channel將數據讀入到Buffer中,而後再從Buffer中取出數據來處理。
在NIO中, Buffer是一個頂層父類,它是一個抽象類,經常使用的Buffer的子類有:ByteBuffer、 IntBuffer、 CharBuffer、 LongBuffer、DoubleBuffer、 FloatBuffer、ShortBuffer。
答:
Selector類是NIO的核心類, Selector可以檢測多個註冊的通道上是否有事件發生,若是有事件發生,便獲取事件而後針對每一個事件進行相應的響應處理。這樣一來,只是用一個單線程就能夠管理多個通道,也就是管理多個鏈接。這樣使得只有在鏈接真正有讀寫事件發生時,纔會調用函數來進行讀寫,就大大地減小了系統開銷,而且沒必要爲每一個鏈接都建立一個線程,不用去維護多個線程,而且避免了多線程之間的上下文切換致使的開銷。
答:
jdbc就是典型的反射
Class.forName('com.mysql.jdbc.Driver.class');//加載MySQL的驅動類
這就是反射。如hibernate,struts等框架使用反射實現的。
答:
Class對象的 newInstance()
調用 Constructor 對象的 newInstance()
//獲取 Person 類的 Class 對象 Class clazz=Class.forName("reflection.Person"); //使用.newInstane 方法建立對象 Person p=(Person) clazz.newInstance(); //獲取構造方法並建立對象 Constructor c=clazz.getDeclaredConstructor(String.class,String.class,int.class); //建立對象並設置屬性13/04/2018 Person p1=(Person) c.newInstance("李四","男",20)
答:
使用 Java 對象序列化, 在保存對象時,會把其狀態保存爲一組字節,在將來, 再將這些字節組裝成對象。必須注意地是, 對象序列化保存的是對象的」狀態」,即它的成員變量。由此可知,對象序列化不會關注類中的靜態變量。
答:
虛擬機是否容許反序列化,不只取決於類路徑和功能代碼是否一致,一個很是重要的一點是兩個類的序列化ID是否一致(就是 privatestatic final long serialVersionUID
答:
在 Java 語言裏深複製一個對象,經常能夠先使對象實現Serializable接口,而後把對象(實際上只是對象的一個拷貝)寫到一個流裏,再從流裏讀出來,即可以重建對象。
答:
元註解的做用是負責註解其餘註解。 Java5.0定義了4個標準的meta-annotation類型,它們被用來提供對其它annotation類型做說明。
@Target 修飾的對象範圍
@Target說明了Annotation所修飾的對象範圍: Annotation可被用於packages、types(類、接口、枚舉、Annotation 類型)、類型成員(方法、構造方法、成員變量、枚舉值)、方法參數和本地變量(如循環變量、catch 參數)。在 Annotation 類型的聲明中使用了target可更加明晰其修飾的目標。
@Retention 定義 被保留的時間長短
Retention 定義了該 Annotation 被保留的時間長短:表示須要在什麼級別保存註解信息,用於描述註解的生命週期(即:被描述的註解在什麼範圍內有效),取值(RetentionPoicy)由:
SOURCE:在源文件中有效(即源文件保留)
CLASS:在 class 文件中有效(即 class 保留)
RUNTIME:在運行時有效(即運行時保留)
@Documented 描述-javadoc
@ Documented用於描述其它類型的annotation應該被做爲被標註的程序成員的公共API,所以能夠被例如javadoc此類的工具文檔化。
@Inherited闡述了某個被標註的類型是被繼承的
@Inherited元註解是一個標記註解,@Inherited闡述了某個被標註的類型是被繼承的。若是一個使用了@Inherited修飾的annotation類型被用於一個class,則這個annotation 將被用於該class的子類。
答:
Annotation(註解)是Java提供的一種對元程序中元素關聯信息和元數據(metadata)的途徑和方法。 Annatation(註解)是一個接口,程序能夠經過反射來獲取指定程序中元素的Annotation對象,而後經過該Annotation對象來獲取註解中的元數據信息。
該面試題答案解析完整文檔獲取方式:Java集合/泛型面試題、Java異常面試題、Java中的IO與NIO面試題、Java反射、Java序列化、Java註解。
篇幅有限,其餘內容就不在這裏一 一展現了,整理不易,歡迎你們一塊兒交流,喜歡小編分享的文章記得關注我點贊喲,感謝支持!重要的事情說三遍,轉發+轉發+轉發,必定要記得轉發哦!!!