CodeGym /Java Blog /ランダム /Java 開発者の職の面接での質問と回答を調査します。パート11
John Squirrels
レベル 41
San Francisco

Java 開発者の職の面接での質問と回答を調査します。パート11

ランダム グループに公開済み
こんにちは! たとえ最速の船であっても、コースがなければ波の上をただ漂ってしまうだけです。 今この記事を読んでいるあなたは間違いなく目標を持っています。重要なのは、コースから外れず、Java 開発者になるために全力を尽くすことです。今日は、理論上のギャップを埋めるために、Java 開発者向けの質問のレビューを続けたいと思います。 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)がtrueを返し、y.equals(z)trueを返す場合、x.equals(z)はtrueを返さなければなりません。

  • 一貫性— 任意の値xおよびyについて、 x.equals(y)を繰り返し呼び出すと、2 つのオブジェクトの比較に使用されるフィールドが各呼び出し間で変更されていない限り、常に同じ値が返されます。

  • null 比較— 任意の値xに対して、x.equals(null)を呼び出すとfalseが返される必要があります。

98.equals() と hashCode() をオーバーライドしないとどうなりますか?

この場合、hashCode() は、オブジェクトが格納されているメモリ セルのアドレスに基づいて生成された数値を返します。つまり、まったく同じフィールドを持つ 2 つのオブジェクトに対して元のhashCode()メソッドが呼び出された場合、結果は異なります (それらは異なるメモリ位置に格納されているため)。元のequals()メソッドは参照を比較します。つまり、参照が同じオブジェクトを指しているかどうかを示します。つまり、比較では==演算子が使用され、フィールドが同一であっても、異なるオブジェクトに対しては常にfalseが返されます。trueは、同じオブジェクトへの参照を比較する場合にのみ返されます。これらのメソッドをオーバーライドしないことが合理的な場合もあります。たとえば、特定のクラスのすべてのオブジェクトを一意にする必要がある場合、これらのメソッドをオーバーライドすると、一意のハッシュ コードの既存の保証が損なわれるだけになる可能性があります。重要なのは、オーバーライドされるかどうかにかかわらず、これらのメソッドのニュアンスを理解し、状況に応じて必要なアプローチを使用することです。

99. x.equals(y) が true を返す場合にのみ対称性要件が満たされるのはなぜですか?

この質問は少し奇妙です。オブジェクト A がオブジェクト B と等しい場合、オブジェクト B はオブジェクト A と等しいです。B がオブジェクト A と等しくない場合、その逆はどのようにして可能でしょうか? これは常識です。

100. ハッシュコードの衝突とは何ですか? どのように対処しますか?

HashCode衝突は、2 つの異なるオブジェクトが同じHashCodeを持つ場合に発生します。そんなことがあるものか?ハッシュ コードは、-2147483648 ~ 2147483647 の範囲の整数にマップされます。つまり、約 40 億の異なる整数の 1 つになります。この範囲は非常に広いですが、無限ではありません。つまり、2 つのまったく異なるオブジェクトが同じハッシュ コードを持つ場合があるということです。可能性は非常に低いですが、可能性はあります。ハッシュ関数の実装が不十分だと、狭い範囲の数値が返されるため、同一のハッシュ コードが頻繁に返され、衝突の可能性が高まります。衝突を減らすには、値を均一に分散し、値が繰り返される可能性を最小限に抑える HashCodeメソッドを適切に実装する必要があります。

101. hashCode コントラクトに参加している要素の値が変更された場合はどうなりますか?

ハッシュ コードの計算に関与する要素が変更されると、オブジェクトのハッシュ コードも変更されるはずです (ハッシュ関数が良好な場合)。不変オブジェクトをHashMapのキーとして使用する必要があるのは、その内部状態 (フィールド) を作成後に変更できないためです。そして、ハッシュ コードは作成後に変更されるということになります。可変オブジェクトをキーとして使用する場合、オブジェクトのフィールドが変更されると、そのハッシュ コードも変更され、 HashMap 内の対応するキーと値のペアが失われる可能性があります。結局、元のハッシュ コードに関連付けられたバケットに保存されますが、オブジェクトが変更された後は、別のバケットで検索することになります。

102. String name フィールドと int age フィールドを持つ Student クラス用に、equals() メソッドと hashCode() メソッドを作成します。

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;
 }
}
等しい():
  • まず、参照を直接比較します。なぜなら、参照が同じオブジェクトを指している場合、同等性をチェックし続けることに何の意味があるのでしょうか。結果がtrueになることはすでにわかっています。

  • null かどうか、およびクラスの型が同じかどうかをチェックします。パラメーターが null または別の型の場合、オブジェクトは等しくならず、結果はfalseになる必要があるためです。

  • パラメーターを同じ型にキャストします (結局のところ、それが親型のオブジェクトである場合はどうなるでしょうか)。

  • プリミティブ フィールドを比較します ( =!を使用した比較で十分です)。等しくない場合はfalseを返します。

  • 非プリミティブ フィールドをチェックして、それが null かどうかを確認し、equalsメソッドを使用します ( Stringクラスがメソッドをオーバーライドするため、比較が正しく実行されます)。両方のフィールドが null であるか、equals がtrueを返した場合、チェックは停止され、メソッドはtrueを返します。

ハッシュコード()
  • ハッシュ コードの初期値をオブジェクトのageフィールドの値に等しく設定します。

  • 現在のハッシュ コードに 31 を乗算し (値の分散を大きくするため)、非プリミティブ String フィールドのハッシュ コードを追加します (null でない場合)。

  • 結果を返します。

  • この方法でメソッドをオーバーライドすると、同じ名前int値を持つオブジェクトが常に同じハッシュ コードを返すことになります。

103. 「if (obj instanceof Student)」と「if (getClass() == obj.getClass())」の使用の違いは何ですか?

それぞれの式が何を行うかを見てみましょう。
  • instanceof は、左側のオブジェクト参照が右側の型のインスタンスであるか、そのサブタイプの 1 つであるかを確認します。

  • 「getClass() == ...」は型が同じかどうかをチェックします。

つまり、getClass()はクラスの特定の ID を返しますが、instanceof は、オブジェクトが単なるサブタイプであってもtrueを返します。これにより、ポリモーフィズムを使用する際の柔軟性が向上します。どちらのアプローチも、その仕組みを正確に理解し、適切な場所に適用すれば、有望です。

104. clone() メソッドについて簡単に説明します。

clone ()メソッドはObjectクラスに属します。その目的は、現在のオブジェクトのクローン (コピー) を作成して返すことです。 Java 開発者の職の面接での質問と回答を調査します。 パート11-2このメソッドを使用するには、Cloneableマーカー インターフェイスを実装する必要があります。
Student implements Cloneable
そして、clone()メソッド自体をオーバーライドします。
@Override
protected Object clone() throws CloneNotSupportedException {
 return super.clone();
}
結局のところ、これはObjectクラスで保護されています。つまり、 Studentクラス内でのみ表示され、外部クラスには表示されません。

105. clone() メソッドとオブジェクト内の参照変数に関して、どのような特別な考慮事項に留意する必要がありますか?

オブジェクトのクローンを作成する場合、プリミティブ値とオブジェクト参照の値のみがコピーされます。これは、オブジェクトに別のオブジェクトを参照するフィールドがある場合、その参照のみが複製され、この他の参照オブジェクトは複製されないことを意味します。これはいわゆる浅いコピーです。では、ネストされたすべてのオブジェクトが複製される完全なコピーが必要な場合はどうすればよいでしょうか? これらが単なる参照のコピーではなく、ヒープ内の個別のメモリ アドレスを占有する個別のオブジェクトの本格的なコピーであることを確認するにはどうすればよいでしょうか? 実際、これはすべて非常に簡単です。内部で参照されるクラスごとに、 clone()メソッドをオーバーライドし、Cloneableマーカー インターフェイスを追加する必要があります。これを実行すると、クローン操作では既存のオブジェクトへの参照がコピーされず、代わりに参照されたオブジェクトがコピーされます。これは、オブジェクト自身をコピーする機能も備えているためです。

例外

106. エラーと例外の違いは何ですか?

例外とエラーは、Throwableのサブクラスです。ただし、それぞれに違いがあります。このエラーは、主にシステム リソースの不足によって発生する問題を示します。そして、私たちのアプリケーションではこのような問題は発生しないはずです。これらのエラーの例には、システム クラッシュやメモリ不足エラーなどがあります。エラーはチェックされていないため、ほとんどの場合実行時に発生します。 Java 開発者の職の面接での質問と回答を調査します。 パート 11 - 3例外とは、実行時およびコンパイル時に発生する可能性のある問題です。これらの問題は通常、開発者として作成するコードで発生します。つまり、これらの例外はより予測可能であり、私たちに依存する可能性が高くなります。対照的に、エラーはよりランダムであり、私たちから独立しています。代わりに、アプリケーションが実行されているシステムの問題に依存します。

107. チェック済み、未チェック、例外、スロー、スローの違いは何ですか?

前に述べたように、例外とは、開発者が作成したコードで (何らかの異常な状況により) 発生する実行時またはコンパイル時のエラーです。 チェック済みとは、メソッドがtry-catchメカニズムを使用して常に処理するか、呼び出し側メソッドに再スローする必要がある例外と呼ばれるものです。throwsキーワードはメソッドがスローする可能性のある例外を示すためにメソッド ヘッダーで使用されます。言い換えれば、呼び出し側メソッドに例外をスローするメカニズムを提供します。 未チェックの例外を処理する必要はありません。これらは予測可能性が低く、可能性も低い傾向があります。とはいえ、必要に応じてそれらを処理することもできます。たとえば、手動で例外をスローする場合は throwを使用します。
throw new Exception();

108. 例外階層とは何ですか?

例外階層は非常に広範囲にわたっています。ここでは十分に説明できないことが多すぎます。したがって、代わりに、その主要なブランチのみを考慮します。 Java 開発者の職の面接での質問と回答を調査します。 パート 11 - 4 ここでは、階層の最上位にThrowableクラスが表示されます。これは例外階層の一般的な祖先であり、次に次のように分割されます。
  • エラー— 重大な未チェックの問題。
  • 例外— チェックできる例外。
例外は、さまざまな未チェックの実行時例外とさまざまなチェック済み例外に分類されます。

109. チェック済み例外とチェックなし例外とは何ですか?

以前お話ししたように:
  • チェック例外は、何らかの方法で処理する必要がある例外です。つまり、それらをtry-catchブロックで処理するか、上記のメソッドにスローする必要があります。これを行うには、メソッド シグネチャにメソッド引数をリストした後、throws <例外タイプ>を使用して、メソッドがその例外をスローできることを示します。これは警告に似ており、呼び出し側メソッドに、その例外を処理する責任を負う必要があることを通知します。

  • 未チェック例外はコンパイル時にチェックされず、通常は予測不可能であるため、処理する必要はありません。チェック例外との主な違いは、 try-catchブロックの使用または再スローによる例外の処理が必須ではなくオプションであることです。

101. try-catch ブロックを使用して例外をキャッチして処理する例を作成します。

try{                                                 // Start of the try-catch block
 throw new Exception();                             // Manually throw an exception
} catch (Exception e) {                              // Exceptions of this type and its subtypes will be caught
 System.out.println("Oops! Something went wrong =("); // Display the exception
}

102. 独自のカスタム例外をキャッチして処理する例を作成します。

まず、 Exceptionを継承する独自の例外クラスを作成し、エラー メッセージを引数として受け取るコンストラクターをオーバーライドしましょう。
public class CustomException extends Exception {

 public CustomException(final String message) {
   super(message);
 }
}
次に、前の質問の例で行ったのと同じように、手動で投げてキャッチします。
try{
 throw new CustomException("Oops! Something went wrong =(");
} catch (CustomException e) {
 System.out.println(e.getMessage());
}
もう一度、コードを実行すると、次の出力が得られます。
おっとっと!何か問題が発生しました =(
Java 開発者の職の面接での質問と回答を調査します。 パート 11 - 5それでは、今日はここまでです!次のパートでお会いしましょう!
コメント
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION