您好,登錄后才能下訂單哦!
這篇文章主要講解了“Java常見的10道面試題是什么”,文中的講解內(nèi)容簡單清晰,易于學(xué)習(xí)與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學(xué)習(xí)“Java常見的10道面試題是什么”吧!
1.什么是并發(fā)修改異常?
什么是并發(fā)修改異常: 當(dāng)我們在遍歷實現(xiàn)了collection接口 與iterator接口的集合時(List、Set、Map), 我們可以通過遍歷索引 也可以通過迭代器進行遍歷。 在我們使用迭代器進行遍歷集合的時候, 會獲取到當(dāng)前集合的迭代對象。 在里面有封裝了迭代器的remove方法 與集合自帶的remove方法, 如果我們調(diào)用迭代器對象的remove方法 是沒問題的, 但是當(dāng)我們調(diào)用集合自帶的remove方法時, 就會產(chǎn)生ConcurrentModificationException 并發(fā)修改異常。 也就是說, 當(dāng)我們通過迭代器進行遍歷集合的時候, 是不允許集合本身在結(jié)構(gòu)上發(fā)生變化的。
2.什么是CopyOnWriteArrayList,它與ArrayList有何不同?
CopyOnWriteArrayList: CopyOnWriteArrayList這是一個 ArrayList的線程安全的變體, 其原理大概可以通俗的理解為: 初始化的時候只有一個容器, 很常一段時間, 這個容器數(shù)據(jù)、 數(shù)量等沒有發(fā)生變化的時候, 大家(多個線程),都是讀取 假設(shè)這段時間里只發(fā)生讀取的操作 同一個容器中的數(shù)據(jù), 所以這樣大家讀到的數(shù)據(jù)都是 唯一、一致、安全的, 但是后來有人往里面增加了一個數(shù)據(jù), 這個時候CopyOnWriteArrayList 底層實現(xiàn) 添加的原理是先copy出一個容器 可以簡稱副本, 再往新的容器里添加這個新的數(shù)據(jù), 最后把新的容器的引用地址 賦值給了之前那個舊的的容器地址, 但是在添加這個數(shù)據(jù)的期間, 其他線程如果要去讀取數(shù)據(jù), 仍然是讀取到舊的容器里的數(shù)據(jù)。 Vector ArrayList CopyOnWriteArrayList 這三個集合類都繼承List接口 1、ArrayList是線程不安全的; 2、Vector是比較古老的線程安全的, 但性能不行; 3、CopyOnWriteArrayList在兼顧了 線程安全的同時, 又提高了并發(fā)性, 性能比Vector有不少提高
3.迭代器和枚舉之間的區(qū)別?
在Java集合中, 我們通常都通過 “Iterator(迭代器)” 或 “Enumeration(枚舉類)” 去遍歷集合。 Enumeration是一個接口,它的源碼如下: package java.util; public interface Enumeration<E> { boolean hasMoreElements() E nextElement(); } Iterator也是一個接口,它的源碼如下: package java.util; public interface Iterator<E> { boolean hasNext(); E next(); void remove(); } 區(qū)別: 1 函數(shù)接口不同 Enumeration只有2個函數(shù)接口。 通過Enumeration, 我們只能讀取集合的數(shù)據(jù), 而不能對數(shù)據(jù)進行修改。 Iterator只有3個函數(shù)接口。 Iterator除了能讀取集合的數(shù)據(jù)之外, 也能數(shù)據(jù)進行刪除操作。 2.Iterator支持fail-fast機制,而Enumeration不支持。 Enumeration 是JDK 1.0添加的接口。 使用到它的函數(shù)包括Vector、Hashtable等類, 這些類都是JDK 1.0中加入的, Enumeration存在的目的 就是為它們提供遍歷接口。 Enumeration本身并沒有支持同步, 而在Vector、Hashtable實現(xiàn)Enumeration時, 添加了同步。 而Iterator 是JDK 1.2才添加的接口, 它也是為了HashMap、ArrayList等集合 提供遍歷接口。 Iterator是支持fail-fast機制的: 當(dāng)多個線程對同一個集合的內(nèi)容進行操作時, 就可能會產(chǎn)生fail-fast事件。 Java API規(guī)范建議, 對于較新的程序, Iterator應(yīng)優(yōu)先于Enumeration, 因為“ Iterator在Java集合框架中 代替Enumeration?!? 64.Hashmap如何同步? 1、使用 synchronized 關(guān)鍵字, 這也是最原始的方法。 synchronized(anObject) { value = map.get(key); } 2、使用 JDK1.5 提供的鎖 Java.util.concurrent.locks.Lock lock.lock(); value = map.get(key); lock.unlock(); 3.可以使用 JDK1.5 提供的讀寫鎖 java.util.concurrent.locks.ReadWriteLock rwlock.readLock().lock(); value = map.get(key); rwlock.readLock().unlock(); 4.使用 JDK1.5 提供的 java.util.concurrent.ConcurrentHashMap 類 該類將 Map 的存儲空間分為若干塊, 每塊擁有自己的鎖, 大大減少了多個線程 爭奪同一個鎖的情況 value = map.get(key); 1、不同步確實最快,與預(yù)期一致。 2、四種同步方式中, ConcurrentHashMap 是最快的, 接近不同步的情況。 3、synchronized 關(guān)鍵字非常慢 4、使用讀寫鎖的讀鎖,比普通所稍慢。 1、如果 ConcurrentHashMap 夠用, 則使用 ConcurrentHashMap。 2、如果需自己實現(xiàn)同步, 則使用 JDK1.5 提供的鎖機制, 避免使用 synchronized 關(guān)鍵字。
5.IdentityHashMap和HashMap的區(qū)別?
前者比較key時是 “引用相等” 而后者是 “對象相等”, 即對于 k1和k2,當(dāng)k1==k2時, IdentityHashMap認(rèn)為兩個key相等, 而HashMap只有在k1.equals(k2) == true 時 才會認(rèn)為兩個key相等。 2.IdentityHashMap 允許使用null作為key和value. 不保證任何Key-value對的之間的順序, 更不能保證他們的順序 隨時間的推移不會發(fā)生變化。 3.IdentityHashMap有其特殊用途, 比如序列化或者深度復(fù)制?;? 者記錄對象代理。 舉個例子, jvm中的所有對象都是獨一無二的, 哪怕兩個對象是同一個class的對象 而且兩個對象的數(shù)據(jù)完全相同, 對于jvm來說, 他們也是完全不同的, 如果要用一個map來記錄這樣jvm中的對象, 你就需要用IdentityHashMap, 而不能使用其他Map實現(xiàn)
6.如何獲取某個日期是當(dāng)月的最后一天?
import java.util.Calendar; public class Test { public static void main(String[] args) { System.out.println(daysCount(2010, 2)); } public static int daysCount(int year, int month) { Calendar cal = Calendar.getInstance(); cal.set(Calendar.YEAR, year); cal.set(Calendar.MONTH, month); cal.set(Calendar.DATE, 0); return cal.get(Calendar.DATE); } }
7.java中會存在內(nèi)存泄漏嗎,請簡單描述
所謂內(nèi)存泄露就是指 一個不再被程序使用的對象或變量 一直被占據(jù)在內(nèi)存中。 Java中有垃圾回收機制, 它可以保證一對象不再被引用的時候, 即對象編程了孤兒的時候, 對象將自動被垃圾回收器 從內(nèi)存中清除掉。 由于Java 使用有向圖的方式 進行垃圾回收管理, 可以消除引用循環(huán)的問題, 例如有兩個對象,相互引用, 只要它們和根進程不可達的, 那么GC也是可以回收它們的。 java中的內(nèi)存泄露的情況: 長生命周期的對象持有 短生命周期對象的引用 就很可能發(fā)生內(nèi)存泄露, 盡管短生命周期對象已經(jīng)不再需要, 但是因為長生命周期對象 持有它的引用而導(dǎo)致不能被回收, 這就是java中內(nèi)存泄露的發(fā)生場景, 通俗地說, 就是程序員可能創(chuàng)建了一個對象, 以后一直不再使用這個對象, 這個對象卻一直被引用, 即這個對象無用 但是卻無法被垃圾回收器回收的, 這就是java中可能出現(xiàn) 內(nèi)存泄露的情況, 例如,緩存系統(tǒng), 我們加載了一個對象放在緩存中(例如放在一個全局map對象中), 然后一直不再使用它, 這個對象一直被緩存引用, 但卻不再被使用。 檢查java中的內(nèi)存泄露, 一定要讓程序?qū)⒏鞣N分支情況 都完整執(zhí)行到程序結(jié)束, 然后看某個對象是否被使用過, 如果沒有, 則才能判定這個對象屬于內(nèi)存泄露。 如果一個外部類的實例對象的方法 返回了一個內(nèi)部類的實例對象, 這個內(nèi)部類對象被長期引用了, 即使那個外部類實例對象不再被使用, 但由于內(nèi)部類持久外部類的實例對象, 這個外部類對象將不會被垃圾回收, 這也會造成內(nèi)存泄露。 內(nèi)存泄露的另外一種情況: 當(dāng)一個對象被存儲進HashSet集合中以后, 就不能修改這個對象中的 那些參與計算哈希值的字段了, 否則,對象修改后的哈希值 與最初存儲進HashSet集合中時的哈希值 就不同了, 在這種情況下, 即使在contains方法使用該對象的 當(dāng)前引用作為的參數(shù)去HashSet集合中 檢索對象, 也將返回找不到對象的結(jié)果, 這也會導(dǎo)致無法從HashSet集合中 單獨刪除當(dāng)前對象, 造成內(nèi)存泄露 68.java中實現(xiàn)多態(tài)的機制是什么? 靠的是父類或接口的 引用指向子類或?qū)崿F(xiàn)類的對象, 調(diào)用的方法是內(nèi)存中 正在運行的那個對象的方法。 Java實現(xiàn)多態(tài)有三個必要條件: 繼承、 重寫、 向上轉(zhuǎn)型。 繼承: 在多態(tài)中必須存在 有繼承關(guān)系的子類和父類。 重寫: 子類對父類中某些方法進行重新定義, 在調(diào)用這些方法時 就會調(diào)用子類的方法。 向上轉(zhuǎn)型: 在多態(tài)中需要將子類的引用 賦給父類對象, 只有這樣該引用才能夠具備 技能調(diào)用父類的方法和子類的方法。 只有滿足了上述三個條件, 我們才能夠在同一個繼承結(jié)構(gòu)中 使用統(tǒng)一的邏輯實現(xiàn)代碼處理不同的對象, 從而達到執(zhí)行不同的行為。 多態(tài)機制遵循的原則概括為 當(dāng)超類對象引用變量引用子類對象時, 被引用對象的類型 而不是引用變量的類型 決定了調(diào)用誰的成員方法, 但是這個被調(diào)用的方法 必須是在超類中定義過的, 也就是說被子類覆蓋的方法, 但是它仍然要根據(jù)繼承鏈中 方法調(diào)用的優(yōu)先級來確認(rèn)方法, 該優(yōu)先級為: this.method(O)、 super.method(O)、 this.method((super)O)、 super.method((super)O)。
8.java中實現(xiàn)多態(tài)的機制是什么?
靠的是父類或接口的 引用指向子類或?qū)崿F(xiàn)類的對象, 調(diào)用的方法是內(nèi)存中 正在運行的那個對象的方法。 Java實現(xiàn)多態(tài)有三個必要條件: 繼承、 重寫、 向上轉(zhuǎn)型。 繼承: 在多態(tài)中必須存在 有繼承關(guān)系的子類和父類。 重寫: 子類對父類中某些方法進行重新定義, 在調(diào)用這些方法時 就會調(diào)用子類的方法。 向上轉(zhuǎn)型: 在多態(tài)中需要將子類的引用 賦給父類對象, 只有這樣該引用才能夠具備 技能調(diào)用父類的方法和子類的方法。 只有滿足了上述三個條件, 我們才能夠在同一個繼承結(jié)構(gòu)中 使用統(tǒng)一的邏輯實現(xiàn)代碼處理不同的對象, 從而達到執(zhí)行不同的行為。 多態(tài)機制遵循的原則概括為 當(dāng)超類對象引用變量引用子類對象時, 被引用對象的類型 而不是引用變量的類型 決定了調(diào)用誰的成員方法, 但是這個被調(diào)用的方法 必須是在超類中定義過的, 也就是說被子類覆蓋的方法, 但是它仍然要根據(jù)繼承鏈中 方法調(diào)用的優(yōu)先級來確認(rèn)方法, 該優(yōu)先級為: this.method(O)、 super.method(O)、 this.method((super)O)、 super.method((super)O)。
9.局部變量和成員變量的區(qū)別?
成員變量與局部變量的區(qū)別 1、在類中的位置不同 成員變量: 在類中方法外面 局部變量: 在方法或者代碼塊中, 或者方法的聲明上 2、在內(nèi)存中的位置不同, 成員變量:在堆中(方法區(qū)中的靜態(tài)區(qū)) 局部變量:在棧中 3、生命周期不同 成員變量: 隨著對象的創(chuàng)建而存在, 隨著對象的消失而消失 局部變量: 隨著方法的調(diào)用或者代碼塊的執(zhí)行 而存在, 隨著方法的調(diào)用完畢或者 代碼塊的執(zhí)行完畢而消失 4、初始值 成員變量: 有默認(rèn)初始值 局部變量: 沒有默認(rèn)初始值, 使用之前需要賦值, 否則編譯器會報錯
10.什么是匿名類,有什么好處?
簡單地說: 匿名內(nèi)部類就是沒有名字的內(nèi)部類。 什么情況下需要使用匿名內(nèi)部類? 如果滿足下面的一些條件, 使用匿名內(nèi)部類是比較合適的: 只用到類的一個實例。 類在定義后馬上用到。 類非常?。⊿UN推薦是在4行代碼以下) 給類命名并不會導(dǎo)致你的代碼更容易被理解。 在使用匿名內(nèi)部類時,要記住以下幾個原則: 匿名內(nèi)部類不能有構(gòu)造方法。 匿名內(nèi)部類不能定義任何靜態(tài)成員、方法和類。 匿名內(nèi)部類不能是 public,protected,private,static。 只能創(chuàng)建匿名內(nèi)部類的一個實例。 一個匿名內(nèi)部類一定是在new的后面, 用其隱含實現(xiàn)一個接口或?qū)崿F(xiàn)一個類。 因匿名內(nèi)部類為局部內(nèi)部類, 所以局部內(nèi)部類的所有限制都對其生效。
感謝各位的閱讀,以上就是“Java常見的10道面試題是什么”的內(nèi)容了,經(jīng)過本文的學(xué)習(xí)后,相信大家對Java常見的10道面試題是什么這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關(guān)知識點的文章,歡迎關(guān)注!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。