内部類可以是靜态(static)的,可以使用 public、protected 和 private 通路控制符,而外部類隻能使用 public,或者預設。
成員式内部類
在外部類内部直接定義(不在方法内部或代碼塊内部)的類就是成員式内部類,它可以直接使用外部類的所有變量和方法,即使是 private 的。外部類要想通路内部類的成員變量和方法,則需要通過内部類的對象來擷取。
1 public class Outer{
2 private int size;
3 public class Inner {
4 public void dostuff() {
5 size++;
6 }
7 }
8 public void testTheInner() {
9 Inner in = new Inner();
10 in.dostuff();
11 }
12 }
成員式内部類如同外部類的一個普通成員。
成員式内部類可以使用各種修飾符,包括 public、protected、private、static、final 和 abstract,也可以不寫。
若有 static 修飾符,就為類級,否則為對象級。類級可以通過外部類直接通路,對象級需要先生成外部的對象後才能通路。
非靜态内部類中不能聲明任何 static 成員。
内部類可以互相調用,例如:
1 class A {
2 // B、C 間可以互相調用
3 class B {}
4 class C {}
5 }
成員式内部類的通路
内部類的對象以成員變量的方式記錄其所依賴的外層類對象的引用,因而可以找到該外層類對象并通路其成員。該成員變量是系統自動為非 static 的内部類添加的,名稱約定為“outClassName.this”。
- 使用内部類中定義的非靜态變量和方法時,要先建立外部類的對象,再由“outObjectName.new”操作符建立内部類的對象,再調用内部類的方法,如下所示:
1 public class Demo{
2 public static void main(String[] args) {
3 Outer outer = new Outer();
4 Outer.Inner inner = outer.new Inner();
5 inner.dostuff();
6 }
7 }
8 class Outer{
9 private int size;
10 class Inner{
11 public void dostuff() {
12 size++;
13 }
14 }
15 }
- static 内部類相當于其外部類的 static 成員,它的對象與外部類對象間不存在依賴關系,是以可直接建立。示例如下:
1 public class Demo{
2 public static void main(String[] args) {
3 Outer.Inner inner = new Outer.Inner();
4 inner.dostuff();
5 }
6 }
7
8 class Outer{
9 private static int size;
10 static class Inner {
11 public void dostuff() {
12 size++;
13 System.out.println("size=" + size);
14 }
15 }
16 }
- 運作結果:
- 由于内部類可以直接通路其外部類的成分,是以當内部類與其外部類中存在同名屬性或方法時,也将導緻命名沖突。是以在多層調用時要指明,如下所示:
1 public class Outer{
2 private int size;
3 public class Inner{
4 private int size;
5 public void dostuff(int size){
6 size++; // 局部變量 size;
7 this.size; // 内部類的 size
8 Outer.this.size++; // 外部類的 size
9 }
10 }
11 }
-
局部内部類
局部内部類(Local class)是定義在代碼塊中的類。它們隻在定義它們的代碼塊中是可見的。
局部類有幾個重要特性:
僅在定義了它們的代碼塊中是可見的;
可以使用定義它們的代碼塊中的任何局部 final 變量;
局部類不可以是 static 的,裡邊也不能定義 static 成員;
局部類不可以用 public、private、protected 修飾,隻能使用預設的;
局部類可以是 abstract 的。
請看下面的代碼:
1 public class Outer {
2 public static final int TOTAL_NUMBER = 5;
3 public int id = 123;
4 public void func() {
5 final int age = 15;
6 String str = "http://www.weixueyuan.net";
7 class Inner {
8 public void innerTest() {
9 System.out.println(TOTAL_NUMBER);
10 System.out.println(id);
11 // System.out.println(str);不合法,隻能通路本地方法的final變量
12 System.out.println(age);
13 }
14 }
15 new Inner().innerTest();
16 }
17 public static void main(String[] args) {
18 Outer outer = new Outer();
19 outer.func();
20 }
21 }
- 運作結果:
匿名内部類
匿名内部類是局部内部類的一種特殊形式,也就是沒有變量名指向這個類的執行個體,而且具體的類實作會寫在這個内部類裡面。
注意:匿名類必須繼承一個父類或實作一個接口。
不使用匿名内部類來實作抽象方法:
abstract class Person {
public abstract void eat();
}
class Child extends Person {
public void eat() {
System.out.println("eat something");
}
}
public class Demo {
public static void main(String[] args) {
Person p = new Child();
p.eat();
}
}
-
可以看到,我們用Child繼承了Person類,然後實作了Child的一個執行個體,将其向上轉型為Person類的引用。但是,如果此處的Child類隻使用一次,那麼将其編寫為獨立的一個類豈不是很麻煩?
這個時候就引入了匿名内部類。使用匿名内部類實作:
1 abstract class Person {
2 public abstract void eat();
3 }
4
5 public class Demo {
6 public static void main(String[] args){
7
8 // 繼承 Person 類
9 new Person() {
10 public void eat() {
11 System.out.println("eat something");
12 }
13 }.eat();
14 }
15 }
-
可以看到,匿名類繼承了 Person 類并在大括号中實作了抽象類的方法。
内部類的文法比較複雜,實際開發中也較少用到,并不打算進行深入講解,各位讀者也不應該将内部類作為學習Java的重點。