【Effective Java】條22:靜態成員類優於非靜態成員類

嵌套類是指定義在其他類裏面的類,其旨在爲外圍類提供服務。嵌套類有四種,分別爲靜態成員類、非靜態成員類、匿名類和局部類,其中非靜態成員類、匿名類和局部類又稱爲內部類。

靜態成員類

靜態成員類是最簡單的嵌套類。靜態成員類是外圍類的靜態成員,且和其他靜態成員一樣遵守相同的訪問規則。注意靜態成員類只能訪問外圍類的靜態成員。使用方法如下Demo所示:

public class StaticMemberOfOutterDemo {

  private int i = 1;
  private static int j = 2;

  public void out_f1() {
    System.out.println("out_f1");
  }

  public static void out_f2() {
    System.out.println("out_f2");
  }

  public static void out_f3() {
    //內部類.屬性/方法
    System.out.println(InnerStaticMember.k);
  }

  static class InnerStaticMember {
    static int k = 3;

    public void inner_f1() {
      //不能訪問外圍類非靜態成員
      //System.out.println(i);
      System.out.println(j);
    }

    public void inner_f2() {
      //不能訪問外圍類out_f1()
      //out_f1();
      out_f2();
    }
  }

}

非靜態成員類

與靜態成員類不同的是,非靜態成員類沒有使用static修飾,且每個非靜態成員的實例都隱式地對應一個外部類的實例。成員內部類不能含有static的變量和方法,但卻可以有static final的變量。非靜態成員類可以訪問外部類中的任何變量或方法。

public class NonStaticMemberOfOutterDemo {
  private int i = 0;
  private static int j = 1;

  private NonStaticMember member = new NonStaticMember();

  public void out_f1() {
    System.out.println(i);
    System.out.println(j);

    member.inner_f1();
    member.inner_f2();
    member.inner_f3();
  }

  public static void out_f2() {
  }

  class NonStaticMember {
    int k = 2;
    //不能聲明爲static
    //static int l = 3;
    static final int L = 3;

    public void inner_f1() {
      System.out.println(i);
      System.out.println(j);
    }

    public void inner_f2() {
      out_f1();
    }

    public void inner_f3() {
      out_f2();
    }
  }
}

匿名類

顧名思義,匿名類就是沒有名字的內部類。若滿足以下條件,使用匿名類比較合適:
- 只用到類的一個實例
- 類在定以後馬上用到
- 類非常小(SUN推薦是在4行以下)
- 給類命名並不會導致你的代碼更容易被理解

使用匿名類,注意以下幾個原則:
- 匿名類不能有構造方法
- 匿名類不能定義任何靜態成員、方法和類
- 匿名類不能是publicprotectedprivatestatic
- 只能創建匿名類的一個實例
- 一個匿名類一定是在new的後面,用其隱含實現一個接口或實現一個類
- 因匿名類爲局部類,所以局部類的所有限制都對其生效

局部類

局部類應該是使用最少的嵌套類。局部類可以和局部變量一樣,聲明在局部變量所在的任何地方,所以局部類不能有訪問說明符。但局部類可以訪問當前代碼塊內的常量和外圍類所有的成員。注意:
- 局部類只能在定義該內部類的方法內實例化,不可以在此方法外實例化
- ==局部類對象不能使用該內部類所在方法的非final局部變量==(經實際測試,是可以調用)

public class LocalClassOfMethodDemo {
  private int s = 100;
  private int out_i = 1;

  public void f(final int k) {
    final int s = 200;
    final int j = 10;

    int i = 1;

    class Inner {
      int s = 300;
      int inner_i = 100;

      Inner(int k) {
        //訪問外部類的屬性
        System.out.println(out_i);
        //訪問方法裏的局部變量
        System.out.println(j);
        //訪問方法裏的局部變量
        System.out.println(i);
        //訪問局部類中的變量
        System.out.println(s);
        //訪問局部類中的變量
        System.out.println(this.s);
        //訪問外部類中的屬性
        System.out.println(LocalClassOfMethodDemo.this.s);
      }
    }

    new Inner(k);
  }

  public static void main(String[] args) {
    LocalClassOfMethodDemo localClassOfMethodDemo = new LocalClassOfMethodDemo();
    localClassOfMethodDemo.f(3);
  }

}

總結

以上四種嵌套類,每種都有各自的應用場景。如果內部類需要定義在方法之外或者類內容比較多,則使用內部成員類,至於是靜態還是非靜態,就看內部類是否需要獲取關聯的外部類實例,需要則爲非靜態成員類,否則反之。不過一般能用靜態成員類的就最好使用靜態成員類,畢竟非靜態都牽涉到個隱藏的實例,佔用資源。如果可以定義在方法內部,且只需使用一次則使用匿名類,否則使用局部類。

擴展閱讀

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