2016年java面試題(2)
2016年java面試題
2016年java面試題之JVM 底層 與 GC
22)64 位 JVM 中,int 的長(zhǎng)度是多數(shù)?
Java 中,int 類(lèi)型變量的長(zhǎng)度是一個(gè)固定值,與平臺(tái)無(wú)關(guān),都是 32 位。意思就是說(shuō),在 32 位 和 64 位 的Java 虛擬機(jī)中,int 類(lèi)型的長(zhǎng)度是相同的。
23)Serial 與 Parallel GC之間的不同之處?
Serial 與 Parallel 在GC執(zhí)行的時(shí)候都會(huì)引起 stop-the-world。它們之間主要不同 serial 收集器是默認(rèn)的復(fù)制收集器,執(zhí)行 GC 的時(shí)候只有一個(gè)線程,而 parallel 收集器使用多個(gè) GC 線程來(lái)執(zhí)行。
24)32 位和 64 位的 JVM,int 類(lèi)型變量的長(zhǎng)度是多數(shù)?
32 位和 64 位的 JVM 中,int 類(lèi)型變量的長(zhǎng)度是相同的,都是 32 位或者 4 個(gè)字節(jié)。
25)Java 中 WeakReference 與 SoftReference的區(qū)別?
雖然 WeakReference 與 SoftReference 都有利于提高 GC 和 內(nèi)存的效率,但是 WeakReference ,一旦失去最后一個(gè)強(qiáng)引用,就會(huì)被 GC 回收,而軟引用雖然不能阻止被回收,但是可以延遲到 JVM 內(nèi)存不足的時(shí)候。
26)WeakHashMap 是怎么工作的?
WeakHashMap 的工作與正常的 HashMap 類(lèi)似,但是使用弱引用作為 key,意思就是當(dāng) key 對(duì)象沒(méi)有任何引用時(shí),key/value 將會(huì)被回收。
27)JVM 選項(xiàng) -XX: UseCompressedOops 有什么作用?為什么要使用?
當(dāng)你將你的應(yīng)用從 32 位的 JVM 遷移到 64 位的 JVM 時(shí),由于對(duì)象的指針從 32 位增加到了 64 位,因此堆內(nèi)存會(huì)突然增加,差不多要翻倍。這也會(huì)對(duì) CPU 緩存(容量比內(nèi)存小很多)的數(shù)據(jù)產(chǎn)生不利的影響。因?yàn)?,遷移到 64 位的 JVM 主要?jiǎng)訖C(jī)在于可以指定最大堆大小,通過(guò)壓縮 OOP 可以節(jié)省一定的內(nèi)存。通過(guò) -XX: UseCompressedOops 選項(xiàng),JVM 會(huì)使用 32 位的 OOP,而不是 64 位的 OOP。
28)怎樣通過(guò) Java 程序來(lái)判斷 JVM 是 32 位 還是 64 位?
你可以檢查某些系統(tǒng)屬性如 sun.arch.data.model 或 os.arch 來(lái)獲取該信息。
29)32 位 JVM 和 64 位 JVM 的最大堆內(nèi)存分別是多數(shù)?
理論上說(shuō)上 32 位的 JVM 堆內(nèi)存可以到達(dá) 2^32,即 4GB,但實(shí)際上會(huì)比這個(gè)小很多。不同操作系統(tǒng)之間不同,如 Windows 系統(tǒng)大約 1.5 GB,Solaris 大約 3GB。64 位 JVM允許指定最大的堆內(nèi)存,理論上可以達(dá)到 2^64,這是一個(gè)非常大的數(shù)字,實(shí)際上你可以指定堆內(nèi)存大小到 100GB。甚至有的 JVM,如 Azul,堆內(nèi)存到 1000G 都是可能的。
30)JRE、JDK、JVM 及 JIT 之間有什么不同?
JRE 代表 Java 運(yùn)行時(shí)(Java run-time),是運(yùn)行 Java 引用所必須的。JDK 代表 Java 開(kāi)發(fā)工具(Java development kit),是 Java 程序的開(kāi)發(fā)工具,如 Java 編譯器,它也包含 JRE。JVM 代表 Java 虛擬機(jī)(Java virtual machine),它的責(zé)任是運(yùn)行 Java 應(yīng)用。JIT 代表即時(shí)編譯(Just In Time compilation),當(dāng)代碼執(zhí)行的次數(shù)超過(guò)一定的閾值時(shí),會(huì)將 Java 字節(jié)碼轉(zhuǎn)換為本地代碼,如,主要的熱點(diǎn)代碼會(huì)被準(zhǔn)換為本地代碼,這樣有利大幅度提高 Java 應(yīng)用的性能。
31)解釋 Java 堆空間及 GC?
當(dāng)通過(guò) Java 命令啟動(dòng) Java 進(jìn)程的時(shí)候,會(huì)為它分配內(nèi)存。內(nèi)存的一部分用于創(chuàng)建堆空間,當(dāng)程序中創(chuàng)建對(duì)象的時(shí)候,就從對(duì)空間中分配內(nèi)存。GC 是 JVM 內(nèi)部的一個(gè)進(jìn)程,回收無(wú)效對(duì)象的內(nèi)存用于將來(lái)的分配。
32)你能保證 GC 執(zhí)行嗎?
不能,雖然你可以調(diào)用 System.gc() 或者 Runtime.gc(),但是沒(méi)有辦法保證 GC 的執(zhí)行。
33)怎么獲取 Java 程序使用的內(nèi)存?堆使用的百分比?
可以通過(guò) java.lang.Runtime 類(lèi)中與內(nèi)存相關(guān)方法來(lái)獲取剩余的內(nèi)存,總內(nèi)存及最大堆內(nèi)存。通過(guò)這些方法你也可以獲取到堆使用的百分比及堆內(nèi)存的剩余空間。Runtime.freeMemory() 方法返回剩余空間的字節(jié)數(shù),Runtime.totalMemory() 方法總內(nèi)存的字節(jié)數(shù),Runtime.maxMemory() 返回最大內(nèi)存的字節(jié)數(shù)。
34)Java 中堆和棧有什么區(qū)別?
JVM 中堆和棧屬于不同的內(nèi)存區(qū)域,使用目的也不同。棧常用于保存方法幀和局部變量,而對(duì)象總是在堆上分配。棧通常都比堆小,也不會(huì)在多個(gè)線程之間共享,而堆被整個(gè) JVM 的所有線程共享。
2016年java面試題之Java
35)“a==b”和”a.equals(b)”有什么區(qū)別?
如果 a 和 b 都是對(duì)象,則 a==b 是比較兩個(gè)對(duì)象的引用,只有當(dāng) a 和 b 指向的是堆中的同一個(gè)對(duì)象才會(huì)返回 true,而 a.equals(b) 是進(jìn)行邏輯比較,所以通常需要重寫(xiě)該方法來(lái)提供邏輯一致性的比較。例如,String 類(lèi)重寫(xiě) equals() 方法,所以可以用于兩個(gè)不同對(duì)象,但是包含的字母相同的比較。
36)a.hashCode() 有什么用?與 a.equals(b) 有什么關(guān)系?
hashCode() 方法是相應(yīng)對(duì)象整型的 hash 值。它常用于基于 hash 的集合類(lèi),如 Hashtable、HashMap、LinkedHashMap等等。它與 equals() 方法關(guān)系特別緊密。根據(jù) Java 規(guī)范,兩個(gè)使用 equal() 方法來(lái)判斷相等的對(duì)象,必須具有相同的 hash code。
37)final、finalize 和 finally 的不同之處?
final 是一個(gè)修飾符,可以修飾變量、方法和類(lèi)。如果 final 修飾變量,意味著該變量的值在初始化后不能被改變。finalize 方法是在對(duì)象被回收之前調(diào)用的方法,給對(duì)象自己最后一個(gè)復(fù)活的機(jī)會(huì),但是什么時(shí)候調(diào)用 finalize 沒(méi)有保證。finally 是一個(gè)關(guān)鍵字,與 try 和 catch 一起用于異常的處理。finally 塊一定會(huì)被執(zhí)行,無(wú)論在 try 塊中是否有發(fā)生異常。
38)Java 中的編譯期常量是什么?使用它又什么風(fēng)險(xiǎn)?
公共靜態(tài)不可變(public static final )變量也就是我們所說(shuō)的編譯期常量,這里的 public 可選的。實(shí)際上這些變量在編譯時(shí)會(huì)被替換掉,因?yàn)榫幾g器知道這些變量的值,并且知道這些變量在運(yùn)行時(shí)不能改變。這種方式存在的一個(gè)問(wèn)題是你使用了一個(gè)內(nèi)部的或第三方庫(kù)中的公有編譯時(shí)常量,但是這個(gè)值后面被其他人改變了,但是你的客戶端仍然在使用老的值,甚至你已經(jīng)部署了一個(gè)新的jar。為了避免這種情況,當(dāng)你在更新依賴 JAR 文件時(shí),確保重新編譯你的程序。
2016年java面試題之Java 集合框架
39) List、Set、Map 和 Queue 之間的區(qū)別?
List 是一個(gè)有序集合,允許元素重復(fù)。它的某些實(shí)現(xiàn)可以提供基于下標(biāo)值的常量訪問(wèn)時(shí)間,但是這不是 List 接口保證的。Set 是一個(gè)無(wú)序集合。
40)poll() 方法和 remove() 方法的區(qū)別?
poll() 和 remove() 都是從隊(duì)列中取出一個(gè)元素,但是 poll() 在獲取元素失敗的時(shí)候會(huì)返回空,但是 remove() 失敗的時(shí)候會(huì)拋出異常。
41)Java 中 LinkedHashMap 和 PriorityQueue 的區(qū)別是什么?
PriorityQueue 保證最高或者最低優(yōu)先級(jí)的的元素總是在隊(duì)列頭部,但是 LinkedHashMap 維持的順序是元素插入的順序。當(dāng)遍歷一個(gè) PriorityQueue 時(shí),沒(méi)有任何順序保證,但是 LinkedHashMap 課保證遍歷順序是元素插入的順序。
42)ArrayList 與 LinkedList 的不區(qū)別?
最明顯的區(qū)別是 ArrrayList 底層的數(shù)據(jù)結(jié)構(gòu)是數(shù)組,支持隨機(jī)訪問(wèn),而 LinkedList 的底層數(shù)據(jù)結(jié)構(gòu)書(shū)鏈表,不支持隨機(jī)訪問(wèn)。使用下標(biāo)訪問(wèn)一個(gè)元素,ArrayList 的時(shí)間復(fù)雜度是 O(1),而 LinkedList 是 O(n)。
43)用哪兩種方式來(lái)實(shí)現(xiàn)集合的排序?
你可以使用有序集合,如 TreeSet 或 TreeMap,你也可以使用有順序的的集合,如 list,然后通過(guò) Collections.sort() 來(lái)排序。
44)Java 中怎么打印數(shù)組?
你可以使用 Arrays.toString() 和 Arrays.deepToString() 方法來(lái)打印數(shù)組。由于數(shù)組沒(méi)有實(shí)現(xiàn) toString() 方法,所以如果將數(shù)組傳遞給 System.out.println() 方法,將無(wú)法打印出數(shù)組的內(nèi)容,但是 Arrays.toString() 可以打印每個(gè)元素。
45) Hashtable 與 HashMap 有什么不同之處?
這兩個(gè)類(lèi)有許多不同的地方,下面列出了一部分:
a) Hashtable 是 JDK 1 遺留下來(lái)的類(lèi),而 HashMap 是后來(lái)增加的。
b)Hashtable 是同步的,比較慢,但 HashMap 沒(méi)有同步策略,所以會(huì)更快。
c)Hashtable 不允許有個(gè)空的 key,但是 HashMap 允許出現(xiàn)一個(gè) null key。
46)Java 中的 HashSet,內(nèi)部是如何工作的?
HashSet 的內(nèi)部采用 HashMap來(lái)實(shí)現(xiàn)。由于 Map 需要 key 和 value,所以所有 key 的都有一個(gè)默認(rèn) value。類(lèi)似于 HashMap,HashSet 不允許重復(fù)的 key,只允許有一個(gè)null key,意思就是 HashSet 中只允許存儲(chǔ)一個(gè) null 對(duì)象。
47)寫(xiě)一段代碼在遍歷 ArrayList 時(shí)移除一個(gè)元素?
該問(wèn)題的關(guān)鍵在于面試者使用的是 ArrayList 的 remove() 還是 Iterator 的 remove()方法。這有一段示例代碼,是使用正確的方式來(lái)實(shí)現(xiàn)在遍歷的過(guò)程中移除元素,而不會(huì)出現(xiàn) ConcurrentModificationException 異常的示例代碼。
48)我們能自己寫(xiě)一個(gè)容器類(lèi),然后使用 for-each 循環(huán)碼?
可以,你可以寫(xiě)一個(gè)自己的容器類(lèi)。如果你想使用 Java 中增強(qiáng)的循環(huán)來(lái)遍歷,你只需要實(shí)現(xiàn) Iterable 接口。如果你實(shí)現(xiàn) Collection 接口,默認(rèn)就具有該屬性。
49)ArrayList 和 HashMap 的默認(rèn)大小是多數(shù)?
在 Java 7 中,ArrayList 的默認(rèn)大小是 10 個(gè)元素,HashMap 的默認(rèn)大小是16個(gè)元素(必須是2的冪)。這就是 Java 7 中 ArrayList 和 HashMap 類(lèi)的代碼片段:
// from ArrayList.java JDK 1.7
private static final int DEFAULT_CAPACITY = 10;
//from HashMap.java JDK 7
static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // aka 16
50)有沒(méi)有可能兩個(gè)不相等的對(duì)象有有相同的 hashcode?
有可能,兩個(gè)不相等的對(duì)象可能會(huì)有相同的 hashcode 值,這就是為什么在 hashmap 中會(huì)有沖突。相等 hashcode 值的規(guī)定只是說(shuō)如果兩個(gè)對(duì)象相等,必須有相同的hashcode 值,但是沒(méi)有關(guān)于不相等對(duì)象的任何規(guī)定。
51)兩個(gè)相同的對(duì)象會(huì)有不同的的 hash code 嗎?
不能,根據(jù) hash code 的規(guī)定,這是不可能的。
52)我們可以在 hashcode() 中使用隨機(jī)數(shù)字嗎?
不行,因?yàn)閷?duì)象的 hashcode 值必須是相同的。參見(jiàn)答案獲取更多關(guān)于 Java 中重寫(xiě) hashCode() 方法的知識(shí)。
53)Java 中,Comparator 與 Comparable 有什么不同?
Comparable 接口用于定義對(duì)象的自然順序,而 comparator 通常用于定義用戶定制的順序。Comparable 總是只有一個(gè),但是可以有多個(gè) comparator 來(lái)定義對(duì)象的順序。
54)為什么在重寫(xiě) equals 方法的時(shí)候需要重寫(xiě) hashCode 方法?
因?yàn)橛袕?qiáng)制的規(guī)范指定需要同時(shí)重寫(xiě) hashcode 與 equal 是方法,許多容器類(lèi),如 HashMap、HashSet 都依賴于 hashcode 與 equals 的規(guī)定。
看過(guò)“2016年java面試題”的人還看了: