Java中有四種inner class,分別是:
- static inner class
- member inner Class
- local inner class
- anonymous inner class
Static inner class:
1 | public class OutterClass { |
static inner class不能存取outter class的memeber或method!若是一定要存取,則memeber或method要用static修飾。
Member inner Class:
1 | public class OutterClass { |
- inner class可以自由存取outter class的member或method。
通常會用private修飾inner class,這樣可以避免公佈太多的細節,違反封裝原則。
Local inner class:
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
30
31public class OutterClass {
private int x = 0;
public void print() {
final int y = 10;
class InnerClass implements Runnable {
public void run() {
while (true) {
System.out.println("The value of x in OutterClass is " + x);
System.out.println("The value of y in print() is " + y);
try {
Thread.sleep(1000);
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
new Thread(new InnerClass()).start();
}
public static void main(String[] args) {
OutterClass outterClass = new OutterClass();
outterClass.print();
}
}inner class可以自由存取outter class的member和method。
- inner class要存取所在method的變數,必須使用final修飾該變數。
原因:以上述例子為例,當呼叫到outterClass.print(),變數y就失去作用了。然而InnerClass要再存取y就會出錯,所以才會使用final修飾變數y。即複製一份變數y給InnerClass使用,且值都不會再改變。Java 8有支援Closure就可以解決此問題。Anonymous inner class:
1
2
3
4
5
6
7
8
9public static void main(String[] args) {
new Runnable() {
public void run() {
System.out.println("I am a anonymous class");
}
};
}
性質和local inner class相同。
如果多個變數為相同名稱時,預設會選用距離inner class最近的變數。不過實務上開發者很少會把變數名稱取為相同,有可能會讓讀者困惑。請參考Shadowing。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21public class ShadowTest {
public int x = 0;
class FirstLevel {
public int x = 1;
void methodInFirstLevel(int x) {
System.out.println("x = " + x);
System.out.println("this.x = " + this.x);
System.out.println("ShadowTest.this.x = " + ShadowTest.this.x);
}
}
public static void main(String... args) {
ShadowTest st = new ShadowTest();
ShadowTest.FirstLevel fl = st.new FirstLevel();
fl.methodInFirstLevel(23);
}
}
結果:1
2
3x = 23
this.x = 1
ShadowTest.this.x = 0