1. 程式人生 > >這些棘手的Java面試題,答案你都知道嗎?

這些棘手的Java面試題,答案你都知道嗎?

棘手的Java面試問題是那些有一些驚喜元素的問題。如果你試圖用常識回答一個棘手的問題,你很可能會因為需要一些特定的知識而失敗。大多數棘手的Java問題來自於令人困惑的概念,如函式過載和覆蓋,多執行緒,掌握非常棘手,字元編碼,檢查與未檢查的異常和Integer溢位等微妙的Java程式設計細節。

回答棘手的Java問題最重要的是態度和分析思維,即使你不知道答案也會有所幫助。在這篇Java文章中,我們將看到下面幾個Java問題,並且需要更多的Java程式語言知識來正確回答它們。

1、以下Java程式列印了什麼?

public class Test { 
    public static void main(String[] args){
        System.out.println(Math.min(Double.MIN_VALUE, 0.0d)); 
    } 
}

不像整數,其中MINVALUE為負,Double的MAXVALUE和MIN_VALUE都是正數。Double.MINVALUE是2 ^( - 1074) ,Double常數,其大小是所有的Double值當中最小。因此,與明顯的答案不同,此程式將列印0.0,因為Double.MINVALUE大於0.向Java開發人員提出了這個問題,他們有3至5年的經驗,令人驚訝的是,近70%的候選人錯了。

2、如果在try或catch塊上放置return語句或System.exit()會發生什麼?最後會阻止執行嗎?

這是一個非常流行的棘手的Java問題,它很棘手,因為許多程式設計師認為無論如何,但finally塊將始終執行。這個問題通過在try或catch塊中放置一個return語句或從try或catch塊呼叫System.exit()來挑戰該概念。在Java中回答這個棘手的問題是,即使你在try塊或catch塊中放入一個return語句,finally塊也會執行,但是如果你從try或catch塊呼叫System.exit(),最後塊將無法執行。

3、您可以在Java中覆蓋私有或靜態方法嗎?

如果要在Java中提出技巧問題,方法覆蓋是一個很好的主題。無論如何,你不能在Java中覆蓋私有或靜態方法,如果你在子類中建立一個具有相同返回型別和相同方法引數的類似方法,那麼它將隱藏超類方法,這稱為方法隱藏。

類似地,您不能覆蓋子類中的私有方法,因為它在那裡不可訪問,您要做的是在子類中建立另一個具有相同名稱的私有方法。

4、表示式1.0 / 0.0將返回什麼?它會丟擲異常嗎?任何編譯時錯誤?

雖然Java開發人員知道雙原語型別和Double類,但在進行浮點運算時,他們沒有足夠重視Double.INFINITY,NaN和-0.0以及其他規則來控制涉及它們的算術計算。這個問題的簡單答案是它不會丟擲ArithmeticExcpetion並返回Double.INFINITY。

另外,請注意,即使x本身是NaN,比較x == Double.NaN也始終求值為false。要測試x是否為NaN,應該使用方法呼叫Double.isNaN(x)檢查給定的數字是否為NaN。如果您瞭解SQL,那麼非常接近NULL。

5、Java是否支援多重繼承?

如果C ++可以支援直接的多重繼承,那麼為什麼Java不是Interviewer經常給出的引數。這個問題的答案比它看起來更加微妙,因為Java通過允許介面擴充套件其他介面來支援Type的多個繼承,Java不支援的是多個實現繼承。由於現在Java 8的預設方法提供了Java也存在多種行為繼承,因此這種區別也變得模糊。

6、如果我們將一個關鍵物件放在已經存在的HashMap中會發生什麼?

HashMap如何在Java中執行。HashMap也是一個在Java中建立令人困惑和棘手的問題的熱門話題。這個問題的答案是,如果你再次使用相同的金鑰,那麼它將替換舊的對映,因為HashMap不允許重複金鑰。相同的金鑰將產生相同的雜湊碼,並最終將在桶中的相同位置。

每個儲存桶都包含一個Map.Entry物件的連結列表,其中包含Key和Value。現在,Java將從每個條目中獲取Key物件,並使用equals()方法與此新鍵進行比較,如果返回true,則該條目中的value物件將被新值替換。

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)); 
    } 
}

這個問題的要點在於字元編碼以及字串到位元組陣列轉換的工作原理。在這個程式中,我們首先從一個字元陣列建立一個String,它只有一個字元'\ u0097',之後我們從該String獲取位元組陣列並列印該位元組。由於\ u0097在位元組基本型別的8位範圍內,因此猜測str.getBytes()呼叫將返回包含一個值為-105 ((byte)0x97)的元素的位元組陣列是合理的。

然而,這不是程式列印的,這就是為什麼這個問題很棘手。事實上,程式的輸出是依賴於作業系統和語言環境的。在具有美國語言環境的Windows XP上,上述程式列印[63],如果在Linux或Solaris上執行此程式,則會得到不同的值。

要正確回答這個問題,您需要了解Unicode字元在Java字串值和Java字串中的表示方式,以及字元編碼在String.getBytes()中的作用。

簡單來說,將字串轉換為位元組陣列,Java遍歷字串表示的所有字元,並將每個字元轉換為多個位元組,最後將位元組放在一起。將每個Unicode字元對映到位元組陣列的規則稱為字元編碼。因此,如果在編碼和解碼期間不使用相同的字元編碼,則檢索到的值可能不正確。當我們呼叫 str.getBytes() 而不指定字元編碼方案時,JVM使用平臺的預設字元編碼來完成工作。

預設編碼方案是作業系統和區域設定相關。在Linux上,它是UTF-8,在Windows上具有美國語言環境,預設編碼為Cp1252。這解釋了我們在具有美國語言環境的Windows機器上執行此程式所獲得的輸出。無論使用哪種字元編碼方案,Java總是將編碼未識別的Unicode字元轉換為63,這表示所有編碼中的字元U + 003F。

8、以下在Java中實現compareTo()方法有什麼問題

public int compareTo(Object o){ 
    Employee emp = (Employee) o; 
    return this.id - e.id; }

其中id是整數。 好吧,在你保證id總是正面之前,這個Java問題中的三個沒有錯。當你無法保證id為正或負時,這個Java問題變得棘手。棘手的部分是,如果id變為負數,則減法可能會溢位併產生不正確的結果。

9、你如何確保N執行緒可以在沒有死鎖的情況下訪問N個資源?

如果您不熟悉編寫多執行緒程式碼,那麼這對您來說是一個非常棘手的問題。即使對於沒有真正面臨死鎖和競爭條件的經驗豐富的高階程式設計師來說,這個Java問題也很棘手。這裡的關鍵點是排序,如果您按特定順序獲取資源並以相反的順序釋放資源,則可以防止死鎖。

考慮以下Java程式碼片段,它初始化兩個變數並且兩者都不是易失性的,並且兩個執行緒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);

這個問題的答案是肯定的,執行緒T2可能會列印x = 0.為什麼?因為沒有對編譯器的任何指令,例如synchronized或volatile, bExit = true 可能在編譯器重新排序中在x = 1之前出現。此外,x = 1可能線上程2中不可見,因此執行緒2將載入x = 0。現在,你如何解決它?

向幾個程式設計師提出這個問題時,他們的回答不同,一個人建議讓兩個執行緒在一個共同的互斥鎖上同步,另一個人說這兩個變數都是易變的。兩者都是正確的,因為它會阻止重新排序並保證可見性。

但最好的答案是你只需要使 bExit 成為易失性,然後執行緒2只能列印“x = 1”。x不需要是volatile,因為 當bExit 是volatile 時, 不能在bExit = true之後重新排序x 。