
棘手的Java面試問(wèn)題是那些有一些驚喜元素的問(wèn)題。如果你試圖用常識(shí)回答一個(gè)棘手的問(wèn)題,你很可能會(huì)因?yàn)樾枰恍┨囟ǖ闹R(shí)而失敗。
大多數(shù)棘手的Java問(wèn)題來(lái)自于令人困惑的概念,如函數(shù)重載和覆蓋,多線程,掌握非常棘手,字符編碼,檢查與未檢查的異常和Integer溢出等微妙的Java編程細(xì)節(jié)。
回答棘手的Java問(wèn)題最重要的是態(tài)度和分析思維,即使你不知道答案也會(huì)有所幫助。在這篇Java文章中,我們將看到下面幾個(gè)Java問(wèn)題,并且需要更多的Java編程語(yǔ)言知識(shí)來(lái)正確回答它們。
1以下Java程序打印了什么?
public class Test {
public static void main(String[] args){
System.out.println(Math.min(Double.MIN_VALUE, 0.0d));
}
}
不像整數(shù),其中MINVALUE為負(fù),Double的MAXVALUE和MIN_VALUE都是正數(shù)。
Double.MINVALUE是2 ^( - 1074) ,Double常數(shù),其大小是所有的Double值當(dāng)中最小
。因此,與明顯的答案不同,此程序?qū)⒋蛴?.0,因?yàn)镈ouble.MINVALUE大于0.向Java開(kāi)發(fā)人員提出了這個(gè)問(wèn)題,他們有3至5年的經(jīng)驗(yàn),令人驚訝的是,近70%的候選人錯(cuò)了。
如果在try或catch塊上放置return語(yǔ)句或System.exit()會(huì)發(fā)生什么?最后會(huì)阻止執(zhí)行嗎?

這是一個(gè)非常流行的棘手的Java問(wèn)題,它很棘手,因?yàn)樵S多程序員認(rèn)為無(wú)論如何,但finally塊將始終執(zhí)行。這個(gè)問(wèn)題通過(guò)在try或catch塊中放置一個(gè)return語(yǔ)句或從try或catch塊調(diào)用System.exit()來(lái)挑戰(zhàn)該概念。在Java中回答這個(gè)棘手的問(wèn)題是,即使你在try塊或catch塊中放入一個(gè)return語(yǔ)句,finally塊也會(huì)執(zhí)行,但是如果你從try或catch塊調(diào)用System.exit(),最后塊將無(wú)法運(yùn)行。
3您可以在Java中覆蓋私有或靜態(tài)方法嗎?
如果要在Java中提出技巧問(wèn)題,方法覆蓋是一個(gè)很好的主題。無(wú)論如何,你不能在Java中覆蓋私有或靜態(tài)方法,如果你在子類中創(chuàng)建一個(gè)具有相同返回類型和相同方法參數(shù)的類似方法,那么它將隱藏超類方法,這稱為方法隱藏。
類似地,您不能覆蓋子類中的私有方法,因?yàn)樗谀抢锊豢稍L問(wèn),您要做的是在子類中創(chuàng)建另一個(gè)具有相同名稱的私有方法。
4表達(dá)式1.0 / 0.0將返回什么?它會(huì)拋出異常嗎?任何編譯時(shí)錯(cuò)誤?
雖然Java開(kāi)發(fā)人員知道雙原語(yǔ)類型和Double類,但在進(jìn)行浮點(diǎn)運(yùn)算時(shí),他們沒(méi)有足夠重視Double.INFINITY,NaN和-0.0以及其他規(guī)則來(lái)控制涉及它們的算術(shù)計(jì)算。這個(gè)問(wèn)題的簡(jiǎn)單答案是它不會(huì)拋出ArithmeticExcpetion并返回Double.INFINITY。
另外,請(qǐng)注意,即使x本身是NaN,比較x == Double.NaN也始終求值為false。要測(cè)試x是否為NaN,應(yīng)該使用方法調(diào)用Double.isNaN(x)檢查給定的數(shù)字是否為NaN。如果您了解SQL,那么非常接近NULL。
5Java是否支持多重繼承?
如果C ++可以支持直接的多重繼承,那么為什么Java不是Interviewer經(jīng)常給出的參數(shù)。這個(gè)問(wèn)題的答案比它看起來(lái)更加微妙,因?yàn)镴ava通過(guò)允許接口擴(kuò)展其他接口來(lái)支持Type的多個(gè)繼承,Java不支持的是多個(gè)實(shí)現(xiàn)繼承。由于現(xiàn)在Java 8的默認(rèn)方法提供了Java也存在多種行為繼承,因此這種區(qū)別也變得模糊。
6如果我們將一個(gè)關(guān)鍵對(duì)象放在已經(jīng)存在的HashMap中會(huì)發(fā)生什么?
HashMap如何在Java中運(yùn)行。HashMap也是一個(gè)在Java中創(chuàng)建令人困惑和棘手的問(wèn)題的熱門(mén)話題。這個(gè)問(wèn)題的答案是,如果你再次使用相同的密鑰,那么它將替換舊的映射,因?yàn)镠ashMap不允許重復(fù)密鑰。相同的密鑰將產(chǎn)生相同的哈希碼,并最終將在桶中的相同位置。
每個(gè)存儲(chǔ)桶都包含一個(gè)Map.Entry對(duì)象的鏈接列表,其中包含Key和Value?,F(xiàn)在,Java將從每個(gè)條目中獲取Key對(duì)象,并使用equals()方法與此新鍵進(jìn)行比較,如果返回true,則該條目中的value對(duì)象將被新值替換。
7以下Java程序打印了什么?
public class Test {
public static void main(String[] args) throws Exception {
char[] chars = new char[] {'\u0097'};
String str = new String(chars);
byte[] bytes = str.getBytes();
System.out.println(Arrays.toString(bytes));
}
}
這個(gè)問(wèn)題的要點(diǎn)在于字符編碼以及字符串到字節(jié)數(shù)組轉(zhuǎn)換的工作原理。在這個(gè)程序中,我們首先從一個(gè)字符數(shù)組創(chuàng)建一個(gè)String,它只有一個(gè)字符'\ u0097',之后我們從該String獲取字節(jié)數(shù)組并打印該字節(jié)。
由于\ u0097在字節(jié)基本類型的8位范圍內(nèi),因此猜測(cè)str.getBytes()調(diào)用將返回包含一個(gè)值為-105 ((byte)0x97)的元素的字節(jié)數(shù)組是合理的。
然而,這不是程序打印的,這就是為什么這個(gè)問(wèn)題很棘手。事實(shí)上,程序的輸出是依賴于操作系統(tǒng)和語(yǔ)言環(huán)境的。在具有美國(guó)語(yǔ)言環(huán)境的Windows XP上,上述程序打印[63],如果在Linux或Solaris上運(yùn)行此程序,則會(huì)得到不同的值。
要正確回答這個(gè)問(wèn)題,您需要了解Unicode字符在Java字符串值和Java字符串中的表示方式,以及字符編碼在String.getBytes()中的作用。
簡(jiǎn)單來(lái)說(shuō),將字符串轉(zhuǎn)換為字節(jié)數(shù)組,Java遍歷字符串表示的所有字符,并將每個(gè)字符轉(zhuǎn)換為多個(gè)字節(jié),最后將字節(jié)放在一起。將每個(gè)Unicode字符映射到字節(jié)數(shù)組的規(guī)則稱為字符編碼。因此,如果在編碼和解碼期間不使用相同的字符編碼,則檢索到的值可能不正確。當(dāng)我們調(diào)用 str.getBytes() 而不指定字符編碼方案時(shí),JVM使用平臺(tái)的默認(rèn)字符編碼來(lái)完成工作。
默認(rèn)編碼方案是操作系統(tǒng)和區(qū)域設(shè)置相關(guān)。在Linux上,它是UTF-8,在Windows上具有美國(guó)語(yǔ)言環(huán)境,默認(rèn)編碼為Cp1252。這解釋了我們?cè)诰哂忻绹?guó)語(yǔ)言環(huán)境的Windows機(jī)器上運(yùn)行此程序所獲得的輸出。無(wú)論使用哪種字符編碼方案,Java總是將編碼未識(shí)別的Unicode字符轉(zhuǎn)換為63,這表示所有編碼中的字符U + 003F。
8以下在Java中實(shí)現(xiàn)compareTo()方法有什么問(wèn)題
public int compareTo(Object o){
Employee emp = (Employee) o;
return this.id - e.id; }
其中id是整數(shù)。 好吧,在你保證id總是正面之前,這個(gè)Java問(wèn)題中的三個(gè)沒(méi)有錯(cuò)。當(dāng)你無(wú)法保證id為正或負(fù)時(shí),這個(gè)Java問(wèn)題變得棘手。棘手的部分是,如果id變?yōu)樨?fù)數(shù),則減法可能會(huì)溢出并產(chǎn)生不正確的結(jié)果。
**
9你如何確保N線程可以在沒(méi)有死鎖的情況下訪問(wèn)N個(gè)資源?
**
如果您不熟悉編寫(xiě)多線程代碼,那么這對(duì)您來(lái)說(shuō)是一個(gè)非常棘手的問(wèn)題。即使對(duì)于沒(méi)有真正面臨死鎖和競(jìng)爭(zhēng)條件的經(jīng)驗(yàn)豐富的高級(jí)程序員來(lái)說(shuō),這個(gè)Java問(wèn)題也很棘手。這里的關(guān)鍵點(diǎn)是排序,如果您按特定順序獲取資源并以相反的順序釋放資源,則可以防止死鎖。
考慮以下Java代碼片段,它初始化兩個(gè)變量并且兩者都不是易失性的,并且兩個(gè)線程T1和T2正在修改這些值,如下所示,兩者都不同步
int x = 0;
boolean bExit = false;
Thread 1 (not synchronized)
x = 1;
bExit = true;
Thread 2 (not synchronized)
if (bExit == true)
System.out.println("x=" + x);
這個(gè)問(wèn)題的答案是肯定的,線程T2可能會(huì)打印x = 0.為什么?因?yàn)闆](méi)有對(duì)編譯器的任何指令,例如synchronized或volatile, bExit = true 可能在編譯器重新排序中在x = 1之前出現(xiàn)。此外,x = 1可能在線程2中不可見(jiàn),因此線程2將加載x = 0?,F(xiàn)在,你如何解決它?
向幾個(gè)程序員提出這個(gè)問(wèn)題時(shí),他們的回答不同,一個(gè)人建議讓兩個(gè)線程在一個(gè)共同的互斥鎖上同步,另一個(gè)人說(shuō)這兩個(gè)變量都是易變的。兩者都是正確的,因?yàn)樗鼤?huì)阻止重新排序并保證可見(jiàn)性。
但最好的答案是你只需要使 bExit 成為易失性,然后線程2只能打印“x = 1”。x不需要是volatile,因?yàn)?當(dāng)bExit 是volatile 時(shí), 不能在bExit = true之后重新排序x 。