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

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

ランダム グループに公開済み
皆さん、またこんにちは!私たちは、ジュニア、中級、上級の Java 開発者向けの質問に対する答えを探し続けます。質問はとても興味深いです。私は個人的にそれらを分析するのが好きです。なぜなら、それは私の理論的知識のギャップを発見するのに役立つからです。 前の部分はこの記事 Java 開発者の職の面接での質問と回答を調査します。 パート 2 - 1にあります。しかし、始める前に、次のことを思い出していただきたいと思います。
  1. 情報が不必要に重複しないように、この一連の記事 と重複する質問は省略します。Java Core の面接で最も一般的な (よくある) 質問がカバーされているため、これらの記事を読むことをお勧めします。
  2. 答えをもっと詳しく説明することもできますが、それぞれの答えが記事全体に長くなる可能性があるため、ここでは書きません。そして、就職面接では誰もあなたにそのレベルの詳細を尋ねません。
必要に応じて、より深い研究のためのリンクを残しておきます。飛んでみましょう!

11. Object クラスのすべてのメソッドに名前を付けます

Objectクラスに11 のメソッドがあります。
  1. Class<?> getClass() — 現在のオブジェクトのクラスを取得します。

  2. int hashCode() — 現在のオブジェクトのハッシュ コードを取得します。

  3. booleanquals(Object obj) — 現在のオブジェクトを別のオブジェクトと比較します。

  4. Object clone() — 現在のオブジェクトのコピーを作成して返します。

  5. String toString() — オブジェクトの文字列表現を取得します。

  6. void Notice() — このオブジェクトのモニターで待機している 1 つのスレッドを起動します (スレッドの選択はランダムです)。

  7. void NoticeAll() — このオブジェクトのモニターで待機しているすべてのスレッドを起動します。

  8. void wait() — 現在のスレッドを現在のモニター上で待機させます (現在のスレッドをフリーズします)。

  9. void wait(long timeout) — 現在のスレッドを現在のモニター (現在の同期ブロック上) で待機させますが、待機状態を終了するためのタイムアウト (または、notify または NoticeAll の呼び出しによってスレッドがウェイクアップするまで) を設定します。

  10. void wait(long timeout, int nanos) — このメソッドは前のメソッドと似ていますが、タイムアウトがより正確になります。

  11. void Finalize() — このメソッドは、オブジェクトがガベージ コレクターによって削除される前に (最終的に) 呼び出されます。取得したリソースをクリーンアップするために使用されます。

hashCodeequalsclonetoString、およびFinalizeメソッドを正しく 使用するには、現在のタスクの詳細に従ってこれらのメソッドをオーバーライドする必要があります。

12. リソースを操作する場合の try-with-resources と try-catch-finally の違いは何ですか?

通常、try-catch-finallyを使用する場合、最後のブロックはリソースを閉じるために使用されます。Java 7 では、新しいtry-with-resourcesステートメントが導入されています。これはリソースを解放するための try-catch-finally に似ていますが、よりコンパクトで読みやすくなっています。try-catch-finallyがどのようなもの かを思い出してください。
String text = "some text......";
BufferedWriter bufferedWriter = null;
try {
   bufferedWriter = new BufferedWriter(new FileWriter("someFileName"));
   bufferedWriter.write(text);
} catch (IOException e) {
   e.printStackTrace();
} finally {
   try {
       bufferedWriter.close();
   } catch (IOException e) {
       e.printStackTrace();
   }
}
次に、 try-with-resources を使用してこのコードを書き直してみましょう。
String text = "some text......";
try(BufferedWriter bufferedWriter =new BufferedWriter(new FileWriter("someFileName"))) {
   bufferedWriter.write(text);
} catch (IOException e) {
   e.printStackTrace();
}
なんだかもっと簡単になったと思いませんか?単純なコードに加えて、他にも注意すべき点がいくつかあります。
  1. try-with-resourcesでは、括弧内で宣言されたリソース (閉じられるリソース) はAutoCloseableインターフェイスとその唯一のclose()メソッドを実装する必要があります。

    close メソッドは暗黙的なfinallyブロックで実行されます。そうでない場合、プログラムはリソースを閉じる方法を正確にどのように判断するのでしょうか?

    ただし、リソースの実装とその終了メソッドを独自に作成することはほとんどないでしょう。

  2. ブロックは次の順序で実行されます。

    1. tryブロック
    2. 暗黙的なfinallyブロック。
    3. catchブロック。前のステップで発生した例外をキャッチします
    4. 明示的なfinallyブロック。

    原則として、リストの下位にスローされた例外は、上位にスローされた例外を中断します。

try-catch-finallyを使用していて、 tryブロックで例外が発生したと想像してください。次に、指定されたcatchブロックがすぐに実行を開始します。その中に別の例外 (たとえば、エラーをより詳細に説明するメッセージを含む) が記述されており、メソッドでこの例外を上向きにスローしたいとします。次に、finallyブロックが実行され、そこでも例外がスローされます。しかし、今回は違います。このメソッドは最終的にこれら 2 つの例外のうちどちらをスローしますか? 例外は、finallyブロックによってスローされました。しかし今、 try-with-resourcesについて別のポイントに到達しました。同じ状況でtry-with-resources がどのように動作するかを考えてみましょう。close()メソッドでリソースをクローズしようとすると、tryブロックで例外が発生します。つまり、暗黙的なfinallyブロックで例外が発生します。catch ブロックは次の例外のうちどれをキャッチしますか? トライブロックから投げられたもの!暗黙的なFinalブロッ​​ク ( lose()メソッドから)からの例外は無視されます。この例外の無視は、例外抑制とも呼ばれます。

13. ビット演算とは何ですか?

ビット単位の演算は、ビットのシーケンスに対する演算です。これらには、論理演算とビット単位のシフトが含まれます。 論理演算子:
  • ビットごとのAND — ビット値を比較します。ビットを 0 (偽) に設定すると、結果の対応するビットが 0 に設定されます。つまり、比較された値の両方でビットが 1 (真) の場合、結果のビットも 1 になります。

    ANDまたは&として表されます

    例: 10111101 & 01100111 = 00100101

  • ビットごとのOR — この演算は前の演算の逆です。ビットを 1 に設定すると、結果の対応するビットが 1 に設定されます。したがって、両方の比較値でビットが 0 の場合、結果のビットも 0 になります。

    ORまたは|として表されます。

    例: 10100101 | 01100011 = 11100111

  • ビットごとのNOT — この演算子は単一の値に適用されます。ビットを反転(反転)します。つまり、1 だったビットは 0 になります。そして0だったものが1になります。

    NOTまたは~として示されます

    例: ~10100101 = 01011010

  • ビットごとの排他的OR — ビット値を比較します。両方のビットが 1 の場合、結果のビットは 0 になります。両方のビットが 0 の場合、結果のビットは 0 になります。つまり、結果のビットが 1 になるには、ビットの 1 つだけが 1 でなければなりません。他のビットは 0 でなければなりません。

    XORまたは^として表されます

    例: 10100101 ^ 01100011 = 11000110

ビット単位のシフト( >>および<< ) は、オペランドのビットを指定された方向に、指定された桁数だけシフトします。空いた位置はゼロで埋められます。例えば:
  1. 01100011 >> 4 = 00000110
  2. 01100011 << 3 = 00011000
例外は、負の数値を右にシフトする場合です。思い出していただけると思いますが、符号付き数値の最初のビットは符号を示します。このビットが 1 の場合、数値は負になります。負の数をシフトする場合、符号ビットを保持する必要があるため、空いた位置は 0 ではなく 1 で埋められます。例: 10100010 >> 2 = 11101000 つまり、Java には追加の符号なし右シフト演算子 (>>>) があります。この演算子は >> に似ていますが、シフトすると、オペランドが負の数であるか正の数であるかに関係なく、空いた位置は 0 で埋められます。例: 10100010 >>> 2 = 00101000 ビット単位の演算の詳細については、こちらを ご覧ください。 Java でのビット単位のシフトの例として、HashMaps のhash()Java 開発者の職の面接での質問と回答を調査します。 パート 2 - 2メソッドを取り上げます。このメソッドは、キーの特別な内部ハッシュコードを決定するために使用されます。 このメソッドを使用すると、衝突の数を最小限に抑えるために、HashMap 内のデータを均等に分散できます。 Java 開発者の職の面接での質問と回答を調査します。 パート 2 ~ 3

14. Java にはどのような標準的な不変オブジェクトがありますか?

元の値の変更を許可しないオブジェクトは不変です。異なる値を持つ同じ型の新しいオブジェクトを返すメソッドが含まれる場合があります。標準的な不変オブジェクトには次のようなものがあります。
  • Java で最も有名な不変型は間違いなく String です。
  • 標準型をラップするラッパー クラスのインスタンス: Boolean、Character、Byte、Short、Integer、Long、Double、Float。
  • BigInteger オブジェクトと BigDecimal オブジェクト。通常、特に大きな数値に使用されます。
  • スタック トレース (例外のスタック トレースなど) を構成する StackTraceElement オブジェクト。
  • File クラスのオブジェクト — ファイルを変更できますが、同時にオブジェクト自体は変更されません。
  • UUID: 要素を一意に識別するためによく使用されます。
  • java.time パッケージ内のクラスのすべてのオブジェクト。
  • ロケール オブジェクト。地理的、政治的、文化的地域を識別するために使用されます。

15. 通常のオブジェクトに対する不変オブジェクトの利点は何ですか?

  1. 不変オブジェクトはマルチスレッド環境で安全に使用できます。これにより、競合状態によるデータ損失を心配する必要がなくなります。これは、通常のオブジェクトを操作する場合とは異なります。その場合、オブジェクトを並列環境で使用するときに、適切なメカニズムを考えて考案する必要があります。

  2. 不変オブジェクトはマップ内のキーとして適しています。可変オブジェクトを HashMap キーとして使用し、その後オブジェクトの状態が変化すると、データ構造が混乱する可能性があります。オブジェクトはまだ存在しますが、containsKey() を使用すると、オブジェクトが見つからない可能性があります。

  3. 不変オブジェクトは、プログラムの実行中に決して変更すべきではない不変 (定数) データを格納するのに最適です。

  4. もう 1 つの利点は、失敗の原子性です。不変オブジェクトが例外をスローしても、不必要な (壊れた) 状態のままになることはありません。

  5. これらのクラスはテストが簡単です。

  6. コピー コンストラクターやオブジェクト クローン作成の実装などの追加メカニズムは必要ありません。

OOPに関する質問

16. 一般に、手続き型プログラミングと比較した OOP の利点は何ですか?

さて、OOP の利点:
  1. 複雑なアプリケーションは、手続き型プログラミングよりも OOP を使用した方が簡単に作成できます。これは、すべてが小さなモジュール (相互作用するオブジェクト) に分割され、その結果、プログラミングがオブジェクト間の関係に縮小されるためです。

  2. OOP で作成されたアプリケーションは、(設計原則が適切に守られている場合には) 変更するのがはるかに簡単です。

  3. データとデータ操作は両方とも 1 つのエンティティを形成するため、アプリケーション全体に散らばることはありません (手続き型プログラミングではよくあることです)。

  4. カプセル化の原理により、最も重要なデータがユーザーから保護されます。

  5. クラスではそれぞれに独自の値を持つ多数のオブジェクトを作成できるため、同じコードを異なるデータで再利用できます。

  6. 継承とポリモーフィズムにより、(同様の機能を複製する代わりに) 既存のコードを再利用および拡張することもできます。

  7. アプリケーションの拡張は、手続き型アプローチよりも簡単です。

  8. OOP アプローチにより、実装の詳細を抽象化することができます。

17. OOP の欠点を教えてください

残念ながら、次のようなものも存在します。
  1. OOP には多くの理論的知識が必要であり、何かを書く前に習得しておく必要があります。

  2. OOP のアイデアを理解して実際に適用するのはそれほど簡単ではありません (心の底から少し哲学者である必要があります)。

  3. OOP を使用すると、システムの複雑さが増すため、プログラムのパフォーマンスがわずかに低下します。

  4. OOP アプローチでは、すべてがクラス、インターフェイス、メソッドで構成され、通常の変数よりも多くのメモリを消費するため、より多くのメモリが必要になります。

  5. 初期分析に必要な時間は、手続き型アプローチよりも長くなります。

18. 静的ポリモーフィズムと動的ポリモーフィズムとは何ですか?

ポリモーフィズムにより、同じクラスまたはインターフェイスのオブジェクトが異なる動作をすることが可能になります。多型には 2 つのタイプがあり、早期バインディングおよび後期バインディングとも呼ばれます。静的多態性、または早期バインディング:
  • コンパイル時 (プログラムのライフサイクルの初期) に発生します。
  • コンパイル時にどのメソッドを実行するかを決定します。
  • メソッドのオーバーロードは静的多態性の一例です。
  • 早期バインディングには、プライベート、静的、および最終メソッドが含まれます。
  • 継承は早期バインディングには関与しません。
  • 静的多相性には、特定のオブジェクトが関係するのではなく、変数名の左側に表示されるクラス型に関する情報が関係します。
動的多態性、または遅延バインディング:
  • 実行時 (プログラムの実行中) に発生します。
  • 動的ポリモーフィズムは、メソッドが実行時にどの特定の実装を持つかを決定します。
  • メソッドのオーバーライドは動的多態性の一例です。
  • 遅延バインディングとは、特定のオブジェクト、その型の参照、またはそのスーパークラスを割り当てることを意味します。
  • 継承は動的ポリモーフィズムに関連しています。

19. OOP における抽象化の原理の定義を提供する

OOP では、抽象化は、重要でない詳細を除外しながら、オブジェクトの意味のある一連の特性を分離する方法です。つまり、OOP アプローチでプログラムを設計するときは、実装の詳細には立ち入らず、一般的なモデルに焦点を当てます。Java では、抽象化はインターフェイス を通じて実現されます。たとえば、車がありますが、それがインターフェースになります。そして、それとのさまざまな相互作用 (たとえば、エンジンの始動、ギアのシフトなど) は関数であり、実装の詳細を深く掘り下げることなく使用します。実際、運転中は、ギアボックスがどのようにその目的を果たしているのか、キーがどのようにエンジンを始動させるのか、ステアリングホイールがどのように正確に車輪を回転させるのかなどについて正確に考えることはありません。また、一部の機能 (エンジンなど) の実装を置き換えても、それに気付かない可能性があります。それはあなたにとっては重要ではありません。実装の詳細については詳しく調べません。あなたにとって重要なのは、その行動が実行されることです。本質的に、これにより実装の詳細が抽象化されます。今日はこの時点で終了します。続きます。
コメント
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION