ネスト類:静的ネスト類と非静的ネスト類

2371 ワード

自動回転http://www.importnew.com/1153.html
内部タイプはウィキペディアで定義されています.  オブジェクト指向プログラミングにおいて、内部クラス(入れ子類ともいう)は、別のクラスまたはインターフェースで宣言されるクラスです.内部クラスはサブクラスとは異なります.(訳者注:wikiの注釈が間違っています.内部類と入れ子類は完全に同じではありません.詳細は以下の通りです.)
Javaにおいて、上記の定義は以下のような例があり得る.
public final class Clazz {
  private final class InnerClazz implements Runnable {
        public InnerClazz() {
        }
 
        @Override
        public void run() {
            System.out.println("Hello world");
        }
  }
 
  public Clazz() {
  }
 
  public Runnable getRunnable(){
        return new InnerClazz();
  }
}
この例は一つの内部カテゴリを宣言する以外に、他のことは何もしていません.この例を挙げると、ネスト類と内部類の違いを強調したいです.すべてのプログラマがこの点を理解しているわけではないからです.
内部クラス(Inner class)
上のコード例では、内部クラスの「InneraClazz」を宣言しています.getRunnableメソッドを呼び出すたびに、InneraCzzクラスのインスタンスが作成されます.FindBugsでこのコードをデバッグすると、以下の警告メッセージが見えます.SIC:静的な内部タイプであるべきです.このクラスは外部オブジェクトから作成された内部クラスですが、外部オブジェクトへの参照は内蔵されていません.この参照は、内部クラスのインスタンスをより大きくすることができ、外部オブジェクトの生存期間を可能な限り長くすることができる.可能であれば、このクラスは静的に定義されるべきである.
この警告情報はとても明確です.内部類は父類に向けた引用を保留します.だからInneraClazz類が引用されたら、父類はJVMのゴミ回収メカニズムによって自動的にゴミ回収されません.この引用を使用したいなら、以下のような入れ子類は非常に有用です.
public final class Clazz {
    private final class InnerClazz implements Runnable {
        public InnerClazz() {
        }
 
        @Override
        public void run() {
          // print the value of a member of its "parent" class
          // it's possible because the inner class has an implicit reference
          // on the Clazz instance
          System.out.println(_currentNumber);
        }
    }
 
     private int _currentNumber = 0;
 
     public Clazz() {
     }
 
     public Runnable getRunnable() {
            _currentNumber++;
            return new InnerClazz();
     }
}
内部類以外のネスト類(Nested but not inner class)
ClazzのインスタンスとInneraClazzのインスタンスとの間の非常に強固な引用関係を保持する必要がない場合は、InneraCzzを静的なメンバークラス(以下の例ではNestedNotInneraClizzクラス)として宣言します.
public final class Clazz {
     // static keyword is added
    static private final class NestedNotInnerClazz implements Runnable {
        public NestedNotInnerClazz() {
        }
 
        @Override
        public void run() {
          System.out.println("Hello world");
        }
    }
 
    public Clazz() {
    }
 
    public Runnable getRunnable(){
        return new NestedNotInnerClazz();
    }
}