嵌套類:靜態嵌套類和非靜態嵌套類

轉自http://www.importnew.com/1153.html

內部類在維基百科的定義爲:  面向對象編程中,內部類(又叫做嵌套類)是在另一個類或者接口中進行聲明的類。內部類不同於子類(subclass)。(譯者注: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

上面的示例代碼中聲明瞭一個內部類“InnerClazz”。每次調用getRunnable方法的時候InnerClazz類的實例就會被創建出來。如果你在FindBugs中調試這段代碼,你會看到下面這條警告信息:
SIC:應該是個靜態內部類(SIC_INNER_SHOULD_BE_STATIC) 。
這個類是一個由其外部對象創建的內部類,但是它沒有使用內置的指向外部對象的引用。這個引用可以使得內部類實例更大,並且可以使得外部對象的生存期儘可能長。如果可能,這個類應該被定義成靜態的。

這條警告信息很明確:內部類會保留一個指向其父類的引用,因此只要InnerClazz類被引用了,其父類就不能被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實例和InnerClazz實例之間的非常穩固的引用關係,那麼就將InnerClazz聲明爲一個靜態成員類(下面的例子中的NestedNotInnerClazz類)。

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();
    }
}



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章