Java 面接でよくある質問への回答

📚Javaの基本

1. Java の特徴は何ですか?

Java 言語の核となる機能を理解する

  • オブジェクト指向:カプセル化、継承、ポリモーフィズムなどの機能をサポート
  • プラットフォームの独立性:一度書けばどこでも実行 (WORA)
  • 自動メモリ管理:ガベージ コレクション メカニズムによりメモリが自動的に解放されます
  • マルチスレッドのサポート:同時プログラミングを容易にする組み込みスレッドメカニズム
  • 強力なセキュリティ:型チェックや例外処理などのセキュリティ機構を提供する
  • 動的特性:実行時の型チェックと動的読み込み

2. JDK、JRE、JVM の違いは何ですか?

Java 実行環境の 3 層構造を理解する

  • JVM (Java 仮想マシン):仮想マシン、バイトコードを実行してクロスプラットフォーム機能を実現する抽象的なコンピューター
  • JRE (Java ランタイム環境):実行に必要な JVM およびクラス ライブラリを含む実行環境
  • JDK (Java 開発キット):JRE + コンパイラ + デバッグ ツールおよびその他の開発ツールを含む開発ツール キット
  • 包含関係:JDK > JRE > JVM

3. バイトコードとは何ですか?なぜ Java はクロスプラットフォームなのでしょうか?

Java のクロスプラットフォーム メカニズムの原理を深く理解する

  • バイトコードの定義:Javaソースコードのコンパイルによって生成される中間コードで、ファイル拡張子は .class です。
  • クロスプラットフォームの原則:Java source code → bytecode → JVM execution on different platforms
  • 利点:一度コンパイルすれば、どこでも実行できます。 developers don’t need to rewrite code for different platforms
  • 実行プロセス:javacコンパイラが .java ファイルを .class ファイルへコンパイルし、各プラットフォームのJVMがそれを解釈して実行します。

4. Java の基本的なデータ型は何ですか?

Java の型システムをマスターする

  • 整数型:byte (1 byte), short (2 byte), int (4 byte), long (8 byte)
  • 浮動小数点型:float(4バイト)、double(8バイト)
  • 文字タイプ:char (2バイト、Unicodeをサポート)
  • ブール型:ブール値 (1 バイト、true/false)
  • デフォルト値:integer 0, float 0.0, boolean false, char '\u0000'
  • ラッパークラス:Integer、Long、Float、Double、Booleanなど、それぞれに対応する参照型があります。

5. final、finally、finalizeの違いは何ですか?

Distinguish between three similar but completely different concepts

  • final(キーワード):クラスの継承、メソッドのオーバーライド、変数への再代入を禁止するために使います。
  • finally(キーワード):例外の有無にかかわらず実行されるtry-catch-finallyのブロックで、主にリソース解放に使います。
  • finalize(メソッド):ガベージコレクション前に呼ばれるObjectクラスのメソッドでしたが、現在は非推奨です。
  • アプリケーションシナリオ:Final は不変性の制御に使用され、finally は例外の安全性のために使用され、finalize は try-with-resources に置き換えられました。

🎯 オブジェクト指向プログラミング

6. オブジェクト指向とは何ですか? 4つの大きな特徴とは何ですか?

OOP の中心となる概念を理解する

  • オブジェクト指向の定義:オブジェクトに基づいてプログラミングするという考え方。オブジェクトのプロパティと動作を強調します。
  • 4 つの主な機能:
  • 要約:物事の共通の特徴を抽出し、重要でない詳細を無視する
  • パッケージ:内部実装の詳細を隠し、必要なインターフェイスを公開し、セキュリティを向上させます。
  • 継承:サブクラスは親クラスのプロパティとメソッドを継承してコードの再利用を実現します。
  • 多態性:同じインターフェースの異なる実装、実行時の動的バインディング

7. ポリモーフィズムとは何ですか?ポリモーフィズムを実装するにはどのような方法がありますか?

Javaポリモーフィズムメカニズムの深い理解

  • ポリモーフィックの定義:オブジェクトには複数の形式があり、同じメソッド呼び出しでもオブジェクトが異なればパフォーマンスも異なります。
  • 実装方法:
  • コンパイル時のポリモーフィズム (オーバーロード):同じ名前でパラメータが異なるメソッドは、コンパイル時に呼び出す必要があります。
  • 実行時ポリモーフィズム (オーバーライド):親クラスの参照は子クラスのオブジェクトを指し、実際に呼び出されるメソッドはランタイムによって決定されます。
  • 実行時のポリモーフィック条件:継承、書き換え、上方変換
  • 利点:コードの柔軟性と保守性を向上させ、インターフェイス プログラミングをサポートします。

8. インターフェースと抽象クラスの違いは何ですか?

2 つの抽象的なメカニズムの類似点と相違点を比較する

  • 抽象クラス:抽象的な変更を使用すると、抽象メソッドと具象メソッドが存在する可能性があります
  • インターフェース:インターフェイス定義を使用します。デフォルトのメソッドはパブリック抽象です (Java 8 以降はデフォルトの実装をサポートします)。
  • 継承関係:クラスは単一の抽象クラスのみを継承できますが、複数のインターフェイスを実装できます。
  • アクセス修飾子:抽象クラスはプライベート/保護にすることができ、インターフェイスのメンバーはデフォルトでパブリックにすることができます。
  • 変数:抽象クラスにはインスタンス変数があり、インターフェイスには静的定数のみがあります
  • 使用シナリオ:抽象クラスは、コードとインターフェイス定義の仕様を共有するために使用されます。

9. オーバーロードとオーバーライドとは何ですか?

似ているが異なる 2 つの概念を区別する

  • 過負荷:
  • 同一クラスではメソッド名は同じですが、パラメータの型・数・順序が異なります。
  • これはコンパイル時に決定され、静的バインディングに属します。
  • 戻り値の型は異なる場合があります (ただし、戻り値だけでは区別されません)。
  • オーバーライド:
  • サブクラスは親クラスのメソッドを再実装し、メソッドのシグネチャはまったく同じです
  • 実行時に決定され、動的バインディングに属します。
  • 戻り値の型と例外には互換性がある必要があります

10. アクセス修飾子とは何ですか?行動範囲はどこまでですか?

Java のアクセス制御メカニズムをマスターする

  • パブリック:パブリック、すべてのクラスがアクセス可能
  • 保護されています:保護されており、同じパッケージおよびサブクラス内でアクセス可能
  • デフォルト (修飾子なし):デフォルトでは、同じパッケージにアクセスできます
  • プライベート:プライベート、クラス内のみアクセス可能
  • アクセス範囲の比較:パブリック > 保護された > デフォルト > プライベート
  • ベストプラクティス:アクセス権を最小限に抑え、カプセル化の原則に従います。

💾 メモリ管理とガベージコレクション

11. Java メモリ構造には何が含まれますか?

JVM メモリ割り当てについて

  • ヒープ:すべてのスレッドで共有されるオブジェクト インスタンス、ガベージ コレクション用のメイン領域、構成可能なサイズを格納します。
  • スタック:各スレッドに固有のローカル変数とメソッド呼び出しを保存し、自動的にメモリを解放します。
  • メソッドエリア:ストレージクラスの構造情報、ランタイム定数プール、静的変数などはすべてのスレッドで共有されます
  • プログラムカウンター:現在のスレッドによって実行されたバイトコード命令アドレスを記録します。
  • ローカルメソッドスタック:ネイティブメソッドの実行(C/C++コード)

12. ガベージコレクションとは何ですか?ガベージ コレクション アルゴリズムとは何ですか?

GCの仕組みを深く理解する

  • ガベージ コレクションの定義:使用されなくなったオブジェクトによって占有されているメモリを自動的に再利用します
  • 主なアルゴリズム:
  • クリアにマークを付ける:生きているオブジェクトにマークを付け、ゴミを除去し、フラグメントを生成します
  • コピーアルゴリズム:メモリを 2 つの部分に分割し、クリア時に残ったオブジェクトをコピーします。断片化はありませんが、メモリの無駄です。
  • タグの並べ替え:マーキング後の圧縮とデフラグ、断片化はないがパフォーマンスが低下
  • 世代別アルゴリズム:オブジェクトは新世代と旧世代に分けられ、世代が異なれば異なる戦略が使用されます。
  • 利点:メモリリークを回避するための自動メモリ管理

13. ヒープとスタックの違いは何ですか?

2 つの重要なメモリ領域を比較する

  • ストレージコンテンツ:ヒープ オブジェクト、スタックの基本型と参照
  • スレッド:ヒープはすべてのスレッドで共有され、各スレッドは独立したスタックを持ちます。
  • 管理:ヒープはガベージコレクターによって管理され、スタックは自動的に解放されます
  • サイズ:一般にヒープはより大きく、スタックは比較的小さくなります。
  • パフォーマンス:スタック割り当ては高速ですが、ヒープ割り当ては比較的低速です
  • 例外:ヒープ オーバーフロー OutOfMemoryError、スタック オーバーフロー StackOverflowError

14. メモリリークとは何ですか?それを避けるにはどうすればよいでしょうか?

一般的な記憶の問題を認識する

  • メモリ リークの定義:プログラムが要求したメモリが解放できず、メモリが長時間占有されます。
  • よくある理由:
  • 長命オブジェクトは短命オブジェクトを指します
  • コレクション内のオブジェクトが時間内にクリーンアップされない
  • リスナーまたはコールバックが登録解除されていません
  • 静的コレクションは無限に増加します
  • 回避方法:参照を速やかに解放し、リソースの試行を使用し、メモリ使用量を定期的に確認します。

15. 強参照、ソフト参照、弱参照、仮想参照とは何ですか?

Java の 4 つの参照型を理解する

  • 力強い引用:通常の参照。強参照がなくなるまでオブジェクトはリサイクルされません。
  • ソフトリファレンス:メモリが不足している場合に再利用され、キャッシュに使用されます。
  • 弱い参照:次の GC でリサイクルされ、WeakHashMap に使用されます
  • ファントム参照:いつでもリサイクルできますが、オブジェクトのリサイクルを追跡するには参照キューとともに使用する必要があります。
  • リサイクルの優先順位:仮想参照 > 弱参照 > ソフト参照 > 強参照

📦 収集フレームワーク

16. Java Collections Framework の構造は何ですか?

コレクションフレームワークの全体的な概念をマスターする

  • コレクションインターフェイス:
  • リスト:ArrayList、LinkedList など、順序付けされ反復可能
  • 設定:HashSet、TreeSet など、順序付けされておらず、繰り返しのないもの
  • キュー:LinkedList、PriorityQueue などのキュー
  • マップインターフェイス:
  • キーと値のペアのマッピング:ハッシュマップ、ツリーマップ、同時ハッシュマップ
  • 全体的なレベル:イテラブル → コレクション/マップ → 具体的な実装クラス

17. ArrayList と LinkedList の違いは何ですか?

よく使用される 2 つのリスト実装を比較する

  • データ構造:ArrayList は配列に基づいており、LinkedList は二重リンク リストに基づいています
  • ランダムアクセス:ArrayList O(1)、LinkedList O(n)
  • 挿入と削除:ArrayList O(n)、LinkedList O(1)
  • メモリ使用量:ArrayList は連続的、LinkedList は分散しています (ポインタのオーバーヘッド)
  • スレッドの安全性:どちらも同期されていないため、Collections.synchronizedList() または CopyOnWriteArrayList を使用できます。
  • 選択してください:頻繁なクエリには ArrayList を使用し、頻繁な挿入と削除には LinkedList を使用します。

18. HashMapの原理と性能は何ですか?

HashMap の仕組みを深く理解する

  • データ構造:配列 + リンク リスト + 赤黒ツリー (JDK 8+)
  • 仕組み:hash(key) % table.length 競合する場合に配列の添え字、リンク、またはツリーを計算します。
  • 負荷係数:デフォルトは 0.75、使用容量 ≥ 容量 × 負荷率の場合に拡張します。
  • 拡張機構:容量は2倍、要素は再ハッシュ
  • 時間計算量:平均 O(1)、最悪 O(n) (競合が多い場合)
  • スレッドの安全性:同期されていません。マルチスレッドには ConcurrentHashMap または Collections.synchronizedMap() を使用してください

19. HashSet が重複しないようにするにはどうすればよいですか?

Set の重複排除メカニズムを理解する

  • 低レベルの実装:HashMapをベースに、キーは要素、値は固定オブジェクト
  • 重複排除メカニズム:まず hashCode() を比較し、次に、equals() を使用して等しいかどうかを判断します。
  • プロセスを追加:ハッシュを計算→存在するかどうかを確認→存在しない場合は追加→存在する場合は無視
  • カスタムオブジェクト:一貫性を確保するには、equals() と hashCode() を書き直す必要があります
  • パフォーマンス:ハッシュの品質に応じて、追加、削除、検索の平均 O(1)

20. フェイルファストとフェイルセーフとは何ですか?

コレクションの反復子の安全メカニズムを理解する

  • フェイルファスト:
  • 反復プロセス中にコレクションを変更すると、ConcurrentModificationException がスローされます
  • modCount および ExpectedModCount によって検出される
  • ArrayList、HashMap など (スレッドセーフではありません)
  • フェイルセーフ:
  • 反復はコレクションのスナップショットまたはコピーに基づいて行われます。元のコレクションを変更しても反復には影響しません。
  • CopyOnWriteArrayList、ConcurrentHashMap など
  • 使用方法の提案:反復する場合は、イテレータのremove()を使用するか、フェイルセーフコレクションを使用してください。

⚠️例外処理

21. Java例外システム?

Java例外の分類を理解する

  • スロー可能 (ルートクラス):
  • 例外:回復可能な例外
  • エラー:仮想マシンレベルのエラー、回復不能
  • 例外カテゴリ:
  • チェック例外 (チェック済み):IOException など、キャッチまたは宣言する必要があります。
  • 未チェック例外 (未チェック):NullPointerException、IndexOutOfBoundsException などはキャッチできません
  • 一般的な例外:NPE、ClassCastException、ArrayIndexOutOfBoundsException など。

22. Try-Catch-Finally の実行順序は?

例外処理の実行フローをマスターする

  • 通常の状況:試してみる → 最後に → 通常通りに戻る
  • 例外:try → 例外が発生 → catch →finally → 例外が渡されるか返される
  • 最後に特徴:catch で return、throw、System.exit() を実行する場合でも実行する必要があります。
  • 例外:finally の戻り値は try/catch の戻り値をオーバーライドします。
  • リソースのリリース:リソースを自動的に閉じるには、try-with-resources を使用することをお勧めします。
  • ベストプラクティス:例外が失われる原因となるため、finally の戻り値を変更しないでください。

23. 投げる と 投げる はどう違いますか?

2 つの例外処理キーワードを区別する

  • 投げる:
  • 手動で例外インスタンスをスローします。メソッド内で使用する必要があります。
  • 形式: throw new Exception("メッセージ")
  • 投げる:
  • メソッド シグネチャでスローされる可能性のある例外を宣言する
  • 形式: public void method() は IOException をスローします
  • 加工方法:throw は throws によって宣言され、 throws は呼び出し元によって処理されます。
  • アプリケーション:throw は特定の例外処理に使用され、 throws は例外の配信に使用されます。

24. 例外をカスタマイズするにはどうすればよいですか?

プロジェクト固有の例外クラスを作成する

  • 継承関係:Inherit Exception (チェックされた例外) または RuntimeException (チェックされていない例外)
  • 必要な部品:
  • パラメーターなしのコンストラクターを提供する
  • コンストラクターにメッセージを提供する
  • コンストラクターにメッセージと原因を指定します。
  • コード例:public class CustomException extends Exception { ... }
  • ベストプラクティス:明確な命名、明確なドキュメント、および適切な例外クラスの継承

25. try-with-resources 構文の利点は何ですか?

自動リソース管理を理解する

  • 構文:try (InputStream is = ...) { ... } リソースを自動的にクローズします
  • 要件:リソースは AutoCloseable インターフェイスを実装する必要があります
  • 利点:
  • 手動管理せずに自動的に close() メソッドを呼び出します。
  • 抑制された場合の例外の正しい処理
  • コードがより簡潔になり、リソースの漏洩が回避されます。
  • 該当するシナリオ:ファイル、ストリーム、接続、ステートメントなどのリソース クラス。

🔤 文字列、StringBuilder、StringBuffer

26. 文字列は不変ですが、その理由は何ですか?

String 設計の背後にある深い考慮事項を理解する

  • 不変の定義:String オブジェクトは作成後に変更することはできず、変更操作を行うと新しいオブジェクトが返されます。
  • 実装方法:値配列は最終的に変更され、setter メソッドはありません。
  • 不変の理由:
  • 繰り返し作成を避けるための文字列バッファプールの最適化
  • スレッドセーフ、同期不要
  • HashMap キーに適した hashCode キャッシュをサポート
  • 短所:頻繁に変更を行うと、多数の中間オブジェクトが作成されます

27. String、StringBuilder、StringBuffer の違いは何ですか?

適切な文字列操作クラスを選択する

  • 文字列:不変、スレッドセーフ、パフォーマンスが悪い (頻繁に変更される)
  • 文字列ビルダー:可変、非スレッドセーフ、優れたパフォーマンス (シングルスレッド)
  • 文字列バッファ:変更可能、スレッドセーフ (同期メソッド)、平均的なパフォーマンス (マルチスレッド)
  • パフォーマンスの比較:StringBuilder > StringBuffer > 文字列
  • 使用方法の提案:
  • StringBuilder を使用したシングルスレッドの文字列連結
  • マルチスレッド文字列連結用の StringBuffer
  • 変更する必要はありません。文字列を使用してください

28. 文字列定数プールとは何ですか?

文字列キャッシュのメカニズムを理解する

  • 定義:JVM によって維持される文字列キャッシュ (文字列リテラルを保存)
  • 場所:JDK 7+ はヒープ内にあり、以前はメソッド領域にありました
  • 作成メカニズム:
  • 「abc」などのリテラルは、自動的に定数プールに入力されます。
  • new String("abc") "abc" がプールにない場合は追加します
  • intern() メソッド:文字列を定数プールに追加するか、既存の参照を返します
  • 最適化効果:メモリを節約し、文字列比較を高速化します。

29. 文字列が等しいかどうかを比較するにはどうすればよいですか?

文字列を比較する方法を学ぶ

  • == 比較:参照が同じかどうかを比較しますが、内容は比較しません
  • 等しい() 比較:文字列の内容を比較して、それらが同じかどうかを確認します。使用することをお勧めします
  • qualsIgnoreCase() の比較:大文字と小文字の比較内容を無視する
  • CompareTo() 比較:辞書編集的な比較、整数を返す
  • Objects.equals():null 値の安全な比較の処理
  • ベストプラクティス:文字列の内容を比較するには、equals() を使用します。== の使用は避けてください。

30. 文字列連結のパフォーマンス上の問題は何ですか?

文字列連結のパフォーマンスを最適化する

  • 質問:String s = "a" + "b" + "c" は複数の中間オブジェクトとコピーを生成します
  • 理由:文字列は不変であり、結合されるたびに新しいオブジェクトが作成されます。
  • パフォーマンスへの影響:ループを接続する際の時間計算量は O(n²) です
  • 最適化計画:
  • 直接 + ループ外: コンパイラーは StringBuilder に最適化します。
  • StringBuilder または StringBuffer を明示的に使用する
  • String.join()、StringJoiner などのツールを使用します。

🔄 マルチスレッドと同時実行性

31. スレッドとは何ですか?スレッドを作成するにはどうすればよいですか?

スレッドの基本概念と作成方法をマスターする

  • スレッド定義:プロセス内の独立した実行フロー、共有メモリだが独立したスタック
  • 作成方法:
  • スレッドの継承:public class MyThread extends Thread { public void run() {} }
  • 実行可能ファイルを実装します。public class MyRunnable は Runnable を実装します { public void run() {} }
  • 呼び出し可能な実装:戻り値と例外のサポート
  • 違い:単一継承の制限を回避するには、Runnable を推奨します
  • 開始:thread.start() を呼び出します。run() を直接呼び出すことはできません

32. スレッドのライフサイクルとステータス?

スレッドのさまざまな状態遷移を理解する

  • 新しい:スレッドは作成されましたが開始されていません
  • 実行可能:実行可能状態(実行待ちまたは実行中)
  • ブロックされました:ブロック状態、ロックの取得を待機中
  • 待機中:待機状態、他のスレッドからの通知を待っています
  • TIMED_WAITING:指定された時間待つ
  • 終了:スレッドが終了しました
  • 状態遷移:新規 → 実行可能 → ブロック/待機中 → 終了

33. 同期はどのように機能しますか?

Java の組み込みロック メカニズムを理解する

  • 同期メカニズム:オブジェクトの組み込みロックを使用した同期
  • 使用方法:
  • 同期方法:public synchronized void メソッド() {}
  • 同期ブロック:同期(obj) { ... }
  • 仕組み:
  • すべてのオブジェクトにはモニターがあります
  • スレッドはロックを取得し、クリティカル セクションに入り、相互排他的に実行されます。
  • バイトコード:monitorenter、monitorexit
  • 特徴:再入可能、排他的、自動リリース

34. volatile キーワードの役割は何ですか?

メモリの可視性を理解し、命令の並べ替えを無効にする

  • 機能:
  • 可視性:変更が他のスレッドにすぐに表示されるようにする
  • リフロー禁止:コンパイラと CPU の再順序付けの最適化を防止する
  • 実装:メモリバリア、メインメモリからの強制的な読み書き
  • 制限事項:原子性は保証されていないため、同期を置き換えることはできません
  • アプリケーションシナリオ:フラグビット、ダブルチェックシングルトン、ステータスマーク
  • 同期比較:volatile は軽量ですが、機能が制限されています

35. wait()、notify()、notifyAll() の機能と違いは何ですか?

スレッド間の通信メカニズムをマスターする

  • wait():
  • 現在のスレッドはロックを解放し、ウェイクアップされるまで待機します。
  • 同期ブロック内で呼び出す必要があります
  • 通知():
  • 待機中のスレッドを起動します (ランダムに選択)
  • ロックを解放しないでください。ロックを解放する前に、同期ブロックの終わりまで待ってください。
  • すべて通知():
  • 待機中のすべてのスレッドを起動します
  • 使用モード:プロデューサー/コンシューマー モード、モニター モード

💡 面接準備のヒント

基本を深めます。概念を知るだけでなく、原理と実装の詳細も理解する

さらに演習を行ってください:特にマルチスレッドと同時実行に関連するコーディングの実践を通じて知識を定着させる

ソースコードを読んでください:Java ライブラリのソース コード (コレクション、同時実行性など) を学習して理解を深めます。

細部に注意してください:文字列の比較、コレクションの変更などの一般的な落とし穴とベスト プラクティスをマスターする

例:面接中に具体的な例を使ってコンセプトを説明し、表現力を高めます。