JavaRush /Java Blog /Random-TW /Java 開發者訪談問答分析。第11部分

Java 開發者訪談問答分析。第11部分

在 Random-TW 群組發布
你好! 即使是速度最快的船,如果沒有航向,只會隨波逐流。 如果您現在正在閱讀我的文章,那麼您肯定有一個目標。最重要的是不要誤入歧途,而是要堅持到底——成為 Java 開發人員。今天我想繼續為 Java 開發人員分析 250 多個問題,這將幫助您彌補理論中的一些空白。 Java 開發者訪談問答分析。 第 11 - 1 部分

97. 重新定義 Equals 時是否施加了協定重新定義條件?

重寫的equals()方法必須符合下列條件(規則):
  • 自反性- 對於任何值x,像x.equals(x)這樣的表達式應該始終傳回true(當x != null時)。

  • 對稱性- 對於x和y的任何值只有當y.equals(x)傳回true時, x.equals(y )形式的表達式才必須傳回true

  • 傳遞性- 對於xyz的任何值,如果x.equals(y)回傳truey.equals(z)也傳回true,則x.equals(z)必須傳回true

  • 一致性- 對於xy 的任何值,重複呼叫x.equals(y)將始終傳回先前呼叫此方法的值,前提是用於比較兩個物件的欄位在呼叫之間沒有更改。

  • 比較 null - 對於任何值x,呼叫x.equals(null)將傳回false

98. 如果不重寫 Equals 和 HashCode 會發生什麼事?

在這種情況下,hashCode()將傳回一個根據儲存給定物件的記憶體位置產生的數字。也就是說,兩個具有完全相同欄位的物件在呼叫非重寫的hashCode()時會收到不同的值(畢竟它們儲存在不同的記憶體位置)。未重寫的equals()比較引用以查看它們是否指向相同物件。也就是說,透過==進行比較,如果物件具有相同的字段,則始終傳回false。僅當比較對同一物件的參考時才為True 。有時不重寫這些方法是有邏輯的。例如,您希望某個類別的所有物件都是唯一的,而重寫這些方法只會破壞唯一性的邏輯。最主要的是了解重寫和非重寫方法的細微差別,並根據情況使用這兩種方法。

99. 為什麼只有當 x.equals(y) 回傳 true 時對稱性才為 true?

有點奇怪的問題。如果物件 A 等於物件 B,則物件 B 等於物件 A。如果 B 不等於物件 A,那麼相反的情況怎麼可能呢?這是簡單的邏輯。 Java 開發者訪談問答分析。 第 11 - 2 部分

100.HashCode中什麼是碰撞?怎麼處理呢?

hashCode衝突是指兩個不同的物件具有相同的hashCode值的情況。這怎麼可能?事實上,哈希碼映射到Integer類型,而 Integer 類型的範圍從 -2147483648 到 2147483647,即大約 40 億個不同的整數。這個範圍雖然很大,但並不是無限的。因此,兩個完全不同的物件可能具有相同的雜湊碼。這是極不可能的,但也是有可能的。實作不當的雜湊函數也可能會增加相同雜湊碼的頻率,例如,這會傳回小範圍內的數字,從而增加衝突的機會。為了防止衝突,您需要很好地實現 hashCode方法,以使值的分佈最大,並且重複值的機會最小。

101.如果參與HashCode合約的元素改變其值會發生什麼?

如果參與計算雜湊碼的元素發生了變化,那麼物件本身的雜湊碼也會發生變化(如果雜湊函數是好的)。因此,在HashMap中建議使用不可變(不可更改)物件作為鍵,因為它們的內部狀態(欄位)在創建後無法更改。因此,它們的雜湊碼在創建後也不會轉換。如果您使用可變物件作為鍵,那麼當您變更該物件的欄位時,其雜湊碼將會發生變化,因此您可能會在HashMap中遺失該物件。畢竟,它會儲存在原始哈希碼的桶中,更改後會在另一個桶中找到。 Java 開發者訪談問答分析。 第 11 - 3 部分

102.為Student類別編寫Equals和HashCode方法,該類別由String name和intage欄位組成

public class Student {
int age;
String name;

 @Override
 public boolean equals(final Object o) {
   if (this == o) {
     return true;
   }
   if (o == null || this.getClass() != o.getClass()) {
     return false;
   }

   final Student student = (Student) o;

   if (this.age != student.age) {
     return false;
   }
   return this.name != null ? this.name.equals(student.name) : student.name == null;
 }

 @Override
 public int hashCode() {
   int result = this.age;
   result = 31 * result + (this.name != null ? this.name.hashCode() : 0);
   return result;
 }
}
等於:
  • 首先,我們直接比較鏈接,因為如果鏈接指向同一個對象,那麼繼續檢查有什麼意義呢?無論如何,一切都會是真的

  • 檢查 null 和匹配的類別類型,因為如果物件是 null 或其他類型的參數,則表示物件不相等 - false

  • 將參數物件轉換為一種類型(如果它是父類型的物件)。

  • 比較原始類別欄位(畢竟,透過=!進行比較就足夠了),如果欄位不相等 - false

  • 檢查非原始欄位是否為 null 和equals(在String中,該方法被重寫並將正確比較),如果兩個欄位均為 null 或equals,則檢查結束並且該方法傳回true

哈希碼:
  • 將初始哈希碼值設定為物件的Age Primitive 。

  • 將當前雜湊碼乘以 31(以獲得更大的分佈),並添加非原始字串欄位的雜湊碼(如果它不是空)。

  • 返回結果。

  • 由於此雜湊碼覆蓋,具有相同名稱int值的物件將始終傳回相同的值。

103.使用if(objinstanceofStudent)和if(getClass()==obj.getClass())有什麼差別?

讓我們看看每種方法的作用:
  • instanceof檢查左側的物件參考是否為右側類型或其某些子類型的實例。

  • getClass() == ...檢查類型標識。

也就是說,如果getClass()檢查類別的完整標識,那麼即使該物件只是一個子類型,instanceof也會傳回true ,這可以在主動使用多態性時為我們提供更大的靈活性。實際上,如果您了解他們工作的特點並將其應用在正確的地方,這兩種方法都很好。

104. 簡述clone()方法。

Clone()是Object類別的一個方法,其目的是建立並傳回目前物件的克隆(目前物件的副本)。 Java 開發者訪談問答分析。 第 11 - 4 部分要使用它,您需要實作Cloneable標記介面:
Student implements Cloneable
並重寫clone()方法本身:
@Override
protected Object clone() throws CloneNotSupportedException {
 return super.clone();
}
畢竟,在Object類別中它是受保護的,也就是說,它只在Student類別本身中可見,但對外部的類別不可見。

105. 處理引用型別物件欄位的clone()方法有什麼特殊性?

複製物件時,僅複製原始值和物件參考的值。這意味著,如果一個物件在其內部欄位中有到另一個物件的鏈接,那麼只有這個連結將被克隆,而另一個物件本身不會被克隆。事實上,這就是他們所說的表面克隆。那麼,如果您需要克隆所有嵌套物件來進行全面克隆怎麼辦?如何確保這些不是連結的副本,而是堆中其他佔用記憶體單元的物件的完整克隆?事實上,一切都非常簡單 - 為此,您還需要重寫這些內部物件的每個類別中的clone()方法,並添加一個標記介面 - Cloneable。那麼將不會複製對物件的引用,而是物件本身,因為現在它們也具有複製自身的能力。

例外情況

106.錯誤和異常有什麼差別?

異常和錯誤都是Throwable類別的子類別。然而,它們也有不同之處。此錯誤表明主要是由於系統資源不足而出現的問題。我們的應用程式不應該檢測這些類型的問題。一些錯誤的範例是系統崩潰和記憶體不足錯誤。錯誤大多發生在運行時,因為它們屬於未經檢查的類型。 Java 開發者訪談問答分析。 第 11 - 5 部分異常是運行時和編譯時可能發生的問題。通常,這種情況發生在開發人員編寫的程式碼中。也就是說,異常更容易預測,並且更依賴我們作為開發人員。同時,錯誤更加隨機並且更加獨立於我們,而是取決於應用程式運行所在的系統本身的問題。

107.checked和unchecked、異常、拋出、拋出的區別是什麼。

正如我前面所說,異常是開發人員編寫的程式碼在程式執行期間​​和編譯期間發生的錯誤(由於某些異常情況)。 Checked是一種必須始終使用try-catch機制處理或拋出到上述方法中的例外。 Throws用於方法頭中,指示該方法可能拋出的異常。也就是說,這就是將異常「拋出」到上述方法的機制。 未經檢查是一種不需要處理的異常,通常難以預測且不太可能發生。但是,如果需要,也可以對它們進行處理。 throw用於手動拋出異常,例如:
throw new Exception();

108. 例外情況的層次結構是什麼?

異常的層次結構非常龐大和廣泛,甚至太廣泛而無法在這裡講述它的所有內容。因此,我們將只考慮它的關鍵連結: Java 開發者訪談問答分析。 第 11 - 6 部分在層次結構的最頂層,我們看到類 - Throwable - 一個通用類,異常層次結構的祖先,它又分為:
  • 錯誤- 嚴重的、無法檢查的錯誤。
  • 異常- 檢查異常。
異常分為各種非檢查運轉時異常和各種檢查異常。

109.什麼是檢查異常和非檢查異常?

正如我之前所說:
  • 檢查- 您必須以某種方式處理的異常,也就是說,要么在try - catch塊中處理它們,要么將它們“轉發”到上面的方法。為此,在方法簽名中,列出方法參數後,需要使用trows <exception type>關鍵字,它向方法的用戶指示該方法可以拋出此異常(類似於警告)並傳輸處理此方法的用戶的異常的責任。

  • 未檢查的- 不需要處理的異常,因為它們在編譯時不會檢查,並且通常更難預測。也就是說,與 check 的主要區別在於,對於它們來說,這些try-catch或 throwing 機制的工作原理相同,但它們不是強制性的。

101.編寫在方法的try-catch區塊中攔截並處理異常的範例

try{                                                 // начало блока перехвата
 throw new Exception();                             // ручной бросок исключения
} catch (Exception e) {                              // данное исключение и его потомки будут перехватываться
 System.out.println("Упс, что-то пошло не так =("); // вывод некоторого исключения в консоль
}

102.使用自己的異常編寫捕獲和處理異常的範例

首先,讓我們編寫自己的異常類,它繼承自Exception並使用錯誤訊息重寫其構造函數:
public class CustomException extends Exception {

 public CustomException(final String message) {
   super(message);
 }
}
好吧,那麼我們將像上一個問題一樣手動拋出並攔截它:
try{
 throw new CustomException("Упс, что-то пошло не так =(");
} catch (CustomException e) {
 System.out.println(e.getMessage());
}
同樣,當您運行它時,您將在控制台中獲得以下輸出:
哎呀,出了點問題=(
Разбор вопросов и ответов с собеседований на Java-разработчика. Часть 11 - 7您可以在此處了解有關例外情況的更多資訊。好了,這就是今天的全部內容!下一部分見!
留言
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION