內部類別

內部類別與外部類別

在一個類別中,宣告一個類別,這個類別就是內部類別。

包含內部類別的類別稱為外部類別。

內部類別是外部類別的成員。

所謂的成員,就像是屬性、方法,都屬於類別的成員。

1
2
3
4
5
public class Outter { //外部類別
  public class Inner{ // 內部類別
    
  }
}

內部類別是一個類別

一般類別該有的存取權限(public、private、protected、default)、屬性、方法、建構子、匿名程式碼區塊、靜態程式碼區塊、靜態變數、靜態方法…等等,內部類別也有。

建立內部類別

使用new建立內部類別

  1. 先建立外部類別物件
  2. 建立方式如下
    外部類別.內部類別 inner = 外部類別物件.new 內部類別()
    
1
2
3
4
5
6
7
8
9
10
public class Test {
  public static void main(String[] args) {
    Outter outter = new Outter();
    Outter.Inner inner = outter.new Inner();;
  }
}
class Outter { //外部類別
  // 內部類別
  public class Inner { } 
}

外部類別提供public方法

1
2
3
4
5
6
7
8
9
10
11
12
public class Test {
  public static void main(String[] args) {
    Outter outter = new Outter();
    Outter.Inner inner = outter.getInner();
  }
}
class Outter { //外部類別
  public Inner getInner() {
    return new Inner();
  }
  public class Inner {}
}

外部類別的成員屬性是內部類別

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class Test {
  public static void main(String[] args) {
    Outter outter = new Outter();
    // 直接使用內部類別
    outter.inner.print();
  }
}
class Outter {
  public Inner inner; // 成員屬性是內部類別
  public class Inner{
    void print() {}
  }
  public Outter() {
    // 建立Outter物件的時候,建立內部類別
    inner = new Inner();
  }
}

外部類別可以存取private內部類別與屬性

內部類別權限設為private,代表只有外部類別可以存取,其它類別不能存取內部類別。

以下程式碼呼叫private方法與使用private內部類別

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class Test {
  public static void main(String[] args) {
    Outter outter = new Outter();
    outter.callInner();
  }
}
class Outter { //外部類別
  public void callInner() {
    // 建立private內部類別物件
    Inner inner = new Inner();
    // 呼叫private方法
    inner.print();
  }
  private class Inner {
    private void print() {
      System.out.println("私有內部類別的方法");
    }
  }
}
私有內部類別的方法

內部類別建構子

1
2
3
4
5
6
7
8
9
10
11
12
13
public class Test {
  public static void main(String[] args) {
    Outter outter = new Outter();
    Outter.Inner inner = outter.new Inner();;
  }
}
class Outter { //外部類別
  public class Inner{
    Inner() {
      System.out.println("內部類建構子");
    }
  }
}
內部類建構子

內部類別可以存取外部類別所有屬性

外部類別的private變數、方法、靜態變數、靜態方法,在內部類別是可以存取。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
public class Test {
  public static void main(String[] args) {
    Outter outter = new Outter();
    Outter.Inner inner = outter.new Inner();
    inner.print();
  }
}
class Outter {
  private String name = "變數";
  private static String staticval = "靜態變數";
  private static void staticMethod() {
    System.out.println("靜態方法");
  }
  private void method1() {
    System.out.println("方法");
  }
  public class Inner{
    void print() {
      // 呼叫外部private方法
      method1();
      // 使用外部private變數
      System.out.println(name);
      // 呼叫外部private靜態方法
      staticMethod();
      // 外部private靜態變數
      System.out.println(staticval); 
    }
  }
}
方法
變數
靜態方法
靜態變數

內部類別繼承

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public class Test {
  public static void main(String[] args) {
    Outter outter = new Outter();
    outter.callInnerChild();
  }
}
class Outter {
  // 內部類別
  private class Inner{
    void print() {}
  }
  // 繼承內部類別
  private class InnerChild extends Inner {
    // 覆寫父類別的print()
    @Override
    void print() {
      System.out.println("test");
    }
  }
  public void callInnerChild() {
    // 建立private內部類
    InnerChild innerChild = new InnerChild();
    // 呼叫覆寫的方法
    innerChild.print();
  }
}
test

內部類別與外部類別屬性名字相同

內部類別有name,外部類別有name,使用Outter.this,就可以在內部類別取得外部類別的物件。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public class Test {
  public static void main(String[] args) {
    Outter outter = new Outter();
    Outter.Inner inner = outter.new Inner();
    inner.print();
  }
}
class Outter {
  // 外部類別name
  private String name = "Outter";
  public class Inner {
    // 內部類別name
    public String name = "Inner";
    public void print() {
      // 印出內部類別name
      System.out.println("Inner name = " + name);
      // 印出外部類別name
      System.out.println("Outter name = " + Outter.this.name);
    }
  }
}
Inner name = Inner
Outter name = Outter

外部類別.this

Outter.this與建立outter物件,hashCode都是一模一樣,為相同的物件。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class Test {
  public static void main(String[] args) {
    Outter outter = new Outter();
    Outter.Inner inner = outter.new Inner();
    System.out.println(outter.hashCode());
    inner.print();
  }
}
class Outter {
  private String name = "Outter";
  public class Inner {
    public String name = "Inner";
    public void print() {
      System.out.println("Inner = " + Outter.this.hashCode());
    }
  }
}
989110044
Inner = 989110044

區域內部類別

  • 定義在方法或匿名程式碼區塊中的類別
  • 不能使用 public、private 或 protected 修飾
  • 只能被該方法或匿名程式碼區塊的程式碼使用。

方法中的內部類別

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class Test2 {
  public void method1() {
    // 內部類別
    class LocalInner {
      public void method() {
        System.out.println("區域內部類別中的方法");
      }
    }
    LocalInner localInner = new LocalInner();
    localInner.method();
  }

  public static void main(String[] args) {
    Test2 test = new Test2();
    test.method1();
  }
}
區域內部類別中的方法

程式碼區塊的內部類別

將內部類別寫在static{}靜態程式碼區塊中。

不管建立幾次Test物件,在靜態程式碼區塊只執行一次,所以內部類別只被建立一次。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class Test {
  static {
    class Inner {
      public void method() {
        System.out.println("呼叫內部類別方法");
      }
    }
    Inner inner = new Inner();
    inner.method();
  }
  public static void main(String[] args) {
    // 建立3次物件
    Test test1 = new Test();
    Test test2 = new Test();
    Test test3 = new Test();
  }
}
呼叫內部類別方法

區域內部類別繼承

區域內部類別可以被繼承。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public class Test {
  public void method1() {
    class LocalInner {
      public void method() {
        System.out.println("區域內部類別中的方法");
      }
    }
    class InnerChild extends LocalInner{
      @Override
      public void method() {
        System.out.println("子類別覆寫");
      }
    }
    LocalInner child = new InnerChild();
    child.method();
  }
  public static void main(String[] args) {
    Test test = new Test();
    test.method1();
  }
}
子類別覆寫

results matching ""

    No results matching ""