ProgrammingJava開発者

Javaにおける匿名クラスとネストされたクラスの主な特徴、およびそれらの使用に関する落とし穴について説明してください。

Hintsage AIアシスタントで面接を突破

回答。

ネストされたクラスは、別のクラス内で定義されたクラスです。これには以下があります:

  • Static nested classes — 静的ネストされたクラス;インスタンスなしで外部クラスの非静的メンバーにアクセスできません。
  • Inner classes — 非静的ネストされたクラス;外部クラスのすべてのメンバーにアクセスできます。
  • 匿名クラス — 名前のない内部クラスで、通常はインターフェースや抽象クラスを使用する場所で宣言および作成されます。

匿名クラスの例:

Button b = new Button(); b.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // クリック時の動作 } });

特徴:

  • 匿名クラスは、外部スコープのfinal(又はeffectively final)変数にのみアクセスできます。
  • 各内部クラスのインスタンスには、外部クラスのインスタンスへの暗黙の参照が保存されています。
  • タイプ(static/inner)に応じて、メモリリークや予期しない依存関係が発生する可能性があります。

トリッキーな質問。

内部クラス(非静的内部クラス)は静的メソッドや変数を持つことができますか?

答え: いいえ、持つことができません。ただし、定数(static final)を除きます。静的ネストされたクラスのみがstaticメンバーを持つことができます。

例(エラー):

class Outer { class Inner { static int x = 10; // コンパイルエラー! } }

正しいコード:

class Outer { static class StaticNested { static int x = 10; // OK } }

このテーマの細かい点を知らないことによる実際のエラーの例。


ストーリー

Androidアプリケーションで、イベントハンドラーとしてinner classを使用しました。ハンドラーはstaticフィールドに保存され、Activityへの暗黙の参照を保持していたため、Activityが破棄されるとメモリリークが発生し、アプリケーションが「漏れ始め」、最終的にはOutOfMemoryErrorに至りました。


ストーリー

マイクロサービスの1つで、外部変数(イテレータ)を参照する匿名クラスを使用していました。リファクタリング後、変数はeffectively finalではなくなり、コードがコンパイルされなくなった — 開発者はこの制約を思い出すまで原因を長時間探しました。


ストーリー

ライブラリ内でinner class内部に静的変数を使用して、これは一般的なプラクティスだと思っていました。新しいJDKのバージョンでは、標準が制約を厳守するようになったため、プロジェクトがコンパイルされなくなりました。緊急にアーキテクチャの再設計が必要でした。