有些類的定義中包含另一個類的定義。這種處於內部的類稱為內部類(inner class)。
例如:
public class OuterClass
{
public class InnerClass
{
//---This is a inner class.
}
}
InnerClass類嵌套在OuterClass中,並且被聲明為public,因此被OuterClass類之外的對象訪問。
InnerClass類沒有被聲明為OuterClass類的一個靜態成員,因此除非生成了一個OuterClass對象,否則無法生成任何InnerClass對象。但是,當你聲明一個包含嵌套類的類對象時,並不一定會生成嵌套類的對象,這主要由包含嵌套類的類的構造方法決定。
示例1:
class OuterClass
{
class InnerClass
{}
}
public class Test
{
public static void main(String[] args)
{
OuterClass out = new OuterClass();
OuterClass.InnerClass in = out.new InnerClass();
}
}
我們使用OuterClass out = new OuterClass();語句生成了一個OuterClass類對象。然後又使用OuterClass.InnerClass in = out.new InnerClass();語句借助外部類的實例生成了一個內部類的對象。main()方法中的兩條語句也可以用下面的這一條語句替換:
OuterClass.InnerClass in = new OuterClass().new InnerClass();
總之:在一個類(Test)中,創建另一個類(OuterClass)中的非靜態內部類(InnerClass)必須要借助這個外部類(OuterClass)的一個實例。而且這個內部類對象的聲明也必須用OuterClass.InnerClass的形式。
示例2:
public class Test
{
class InnerClass
{}
1
public static void main(String[] args)
{
InnerClass in = new Test().new InnerClass();
}
}
在main()方法中實例化本類的內部類可以用上例的形式。
示例3:
public class Test
{
class InnerClass
{}
InnerClass in = new InnerClass();
public static void main(String[] args)
{}
}
在main()方法外,實例化本類的內部類就和我們平常的操作一樣了。
示例4:
public class Test
{
class InnerClass
{}
public void method()
{
InnerClass in = new InnerClass();
}
public static void main(String[] args)
{}
}
在本類的非靜態方法中,實例化本類的內部類也和我們平常的操作一樣。
為了讓內部類的對象不依賴於外部類的對象,你可以把內部類聲明為static。
示例5:
class OuterClass
{
static class InnerClass
{}
}
public class Test
{
public static void main(String[] args)
{
2
OuterClass.InnerClass in = new OuterClass.InnerClass();
}
}
從這個例子我們可以看出:創建InnerClass類的對象不再需要OuterClass類的對象。但依然要用OuterClass.InnerClass這個形式聲明in對象。
示例6:
class Outer
{
static int outer_stat = 0;
int outer_non_stat = 1;
static class StaticInner
{
static int stat = 2;
static int stat_test = outer_stat;
public void tester()
{
System.out.println("outer_stat = " + outer_stat);
}
}
class NonStaticInner
{
public void tester()
{
System.out.println("outer_stat = " + outer_stat);
System.out.println("outer_non_stat = " + outer_non_stat);
System.out.println("StaticInner.stat = " + StaticInner.stat);
}
}
}
public class Test
{
public static void main(String[] args)
{
new Outer().new NonStaticInner().tester();
System.out.println("------------");
new Outer.StaticInner().tester();
}
}
輸出結果:
outer_stat = 0
outer_non_stat = 1
StaticInner.stat = 2
3
------------
outer_stat = 0
NonStaticInner類中的System.out.println("outer_stat = " + outer_stat);語句說明:非靜態內部類的非靜態成員可以訪問外部類的靜態變量。
System.out.println("outer_non_stat = " + outer_non_stat);語句說明:非靜態內部類的非靜態成員可以訪問外部類的非靜態變量。
System.out.println("StaticInner.stat = " + StaticInner.stat);語句說明:非靜態內部類的非靜態成員可以訪問相同外部類下的靜態內部類的靜態變量。
StaticInner類中的System.out.println("outer_stat = " + outer_stat);語句說明:靜態內部類的非靜態成員可以訪問外部類的靜態變量。
static int stat_test = outer_stat;語句說明:靜態內部類的靜態成員可以訪問外部類的靜態變量。
注意:靜態內部類可以有靜態成員,而非靜態內部類則不能有靜態成員。
示例7:
class Outer
{
public void tester()
{
class Inner
{}
}
}
public class Test
{
public static void main(String[] args)
{}
}
可以在一個方法中定義一個類,這個類稱為本地內部類。只能在本地,也就是說在該類定義出現的方法中生成一個本地內部類的對象。這種處理適用於一個方法中的計算要求使用一種特殊的類,而這個類在其他地方根本不需要的時候。
本地內部類可以引用其定義出現所在的方法中聲明的變量,當且僅當這種變量是final型的。請看示例8。
示例8:
class Outer
{
public void tester()
{
final int i = 5;
class Inner
{
int j = i;
4
}
Inner in = new Inner();
}
}
public class Test
{
public static void main(String[] args)
{}
}
最後來講解匿名內部類。簡單地說:匿名內部類就是沒有名字的內部類。什麼情況下需要使用匿名內部類?如果滿足下面的一些條件,使用匿名內部類是比較合適的:
·只用到類的一個實例。
·類在定義後馬上用到。
·類非常小(SUN推薦是在4行代碼以下)
·給類命名並不會導致你的代碼更容易被理解。
在使用匿名內部類時,要記住以下4個原則:
·匿名內部類不能有構造方法。
·匿名內部類不能定義任何靜態成員、方法和類。
·匿名內部類不能是public,protected,private,static。
·只能創建匿名內部類的一個實例。
下面是匿名內部類的用法舉例。請讀者通過例子來體會匿名內部類的用法。
示例9:(注意:匿名內部類以";"結束)
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class Test extends JFrame
{
Test()
{
super("test_title");
Container cp = getContentPane();
cp.setLayout(new FlowLayout());
JButton btn = new JButton("close");
cp.add(btn);
btn.addActionListener(act);
setSize(300,200);
}
ActionListener act = new ActionListener()
{
public void actionPerformed(ActionEvent e)
5
{
System.exit(0);
}
};
public static void main(String[] args)
{
Test test = new Test();
test.setVisible(true);
}
}
示例10:(根據示例8改編)
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class Test extends JFrame
{
Test()
{
super("test_title");
Container cp = getContentPane();
cp.setLayout(new FlowLayout());
JButton btn = new JButton("close");
cp.add(btn);
btn.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
System.exit(0);
}
});
}
public static void main(String[] args)
{
Test test = new Test();
test.setSize(300,200);
test.setVisible(true);
}
}
示例11:
public class Test
{
public static void main(String[] args)
6
{
Thread r = new Thread()
{
public void run()
{
for(int k=0;k<10;k++)
{
System.out.print(k);
}
}
};
r.start();
}
}
示例12:(根據示例11改編)
public class Test
{
public static void main(String[] args)
{
new Thread(new Runnable()
{
public void run()
{
System.out.println("run");
}
}).start();
}
}
示例11和12的程序並沒有什麼實際用處,在實際編程時幾乎沒有人這樣寫程序。但這兩個程序有助於我們理解匿名內部類的用法。