內部類,計算機面向對象程序設計概念。向對象程序設計中,可以在一個類的內部定義另一個類,這種類稱為嵌套類(nested classes),它有兩種類型,即靜態嵌套類和非靜態嵌套類。靜態嵌套類使用很少,最重要的是非靜態嵌套類,也即是被稱作為內部類(inner)。內部類是Java語言的主要附加部分。內部類幾乎可以處於一個類內部任何位置,可以與實例變量處於同一級,或處於方法之內,甚至是一個表達式的一部分。
1. 普通內部類
普通內部類的一個最簡單的例子:
- // 外部類
- class OutterClass {
- // 內部類
- public class InnerClass {
- private int i = 0;
- public int getInt(){
- return i;
- }
- }
- public void proc(){
- InnerClass inClass = new InnerClass();
- System.out.println(inClass.getInt());
- }
- }
- public class Main {
- public static void main(String[] args) {
- OutterClass outClass = new OutterClass();
- outClass.proc();
- }
- }
外部類可以訪問內部類的私有成員,內部類也可以訪問外部類的私有成員:
- // 外部類
- class OutterClass {
- private int mOut = 10;
- // 內部類
- public class InnerClass {
- private int mIn = 0;
- public void printOutPrivate(){
- // 直接打印外部類的成員
- System.out.println(mOut);
- }
- }
- public void printInPrivate(){
- InnerClass inClass = new InnerClass();
- // 直接打印內部類的私有成員
- System.out.println(inClass.mIn);
- }
- public void printOutPrivate(){
- InnerClass inClass = new InnerClass();
- inClass.printOutPrivate();
- }
- }
- public class Main {
- public static void main(String[] args) {
- OutterClass outClass = new OutterClass();
- outClass.printInPrivate();
- outClass.printOutPrivate();
- }
- }
如果外部類的成員變量與內部類的成員變量名字相同,當內部類要訪問外部類的該成員時,可以使用“OutClass.this.mem”來區分:
- // 外部類
- class OutterClass {
- private int mMem = 10;
- // 內部類
- public class InnerClass {
- private int mMem = 0;
- public void printOutPrivate(){
- // 直接打印外部類的成員
- System.out.println(OutterClass.this.mMem);
- }
- }
- }
要創建普通內部類,必須先創建相應的外部類:
- // 外部類
- class OutterClass {
- private int mMem = 10;
- // 內部類
- public class InnerClass {
- private int mMem = 0;
- public void printOutPrivate(){
- // 直接打印外部類的成員
- System.out.println(OutterClass.this.mMem);
- }
- }
- }
- public class Main {
- public static void main(String[] args) {
- OutterClass outClass = new OutterClass();
- OutterClass.InnerClass inClass = outClass.new InnerClass();
- inClass.printOutPrivate();
- }
- }
也可以用下面的方式:
- // 外部類
- class OutterClass {
- private int mMem = 10;
- // 內部類
- public class InnerClass {
- private int mMem = 0;
- public void printOutPrivate(){
- // 直接打印外部類的成員
- System.out.println(OutterClass.this.mMem);
- }
- }
- public InnerClass newInnerClass() {
- return new InnerClass();
- }
- }
- public class Main {
- public static void main(String[] args) {
- OutterClass outClass = new OutterClass();
- OutterClass.InnerClass inClass = outClass.newInnerClass();
- inClass.printOutPrivate();
- }
- }
2. 靜態內部類
普通內部類前面加上static修飾符,就成為靜態內部類,靜態內部類類似於C++的嵌套類,與普通內部類相比有如下區別:
靜態內部類沒有指向外部類的引用,外部類對於它來說更像一個名字空間。
普通內部類不能有靜態成員,靜態方法,或另一個靜態內部類;而靜態內部類可以有這一切。
靜態內部類可以直接創建,不必先創建外部類:
- // 外部類
- class OutterClass {
- private int mMem = 0;
- // 靜態內部類
- static public class InnerClass {
- private int mMem = 0;
- public void printOutPrivate(){
- // 這是錯誤的
- // System.out.println(OutterClass.this.mMem);
- }
- }
- public void printInPrivate() {
- InnerClass inClass = new InnerClass();
- // 可以直接訪問靜態內部類的成員
- System.out.println(inClass.mMem);
- }
- }
- public class Main {
- public static void main(String[] args) {
- // 直接創建靜態內部類
- OutterClass.InnerClass inClass = new OutterClass.InnerClass();
- inClass.printOutPrivate();
- }
- }
從上面描述可以看出,靜態內部類與一般類沒有太大區別,只不過它是放在一個類的裡面,這個類相當於它的名字空間,可以防止命名沖突。
3. 局部內部類
Java可以把一個類定義在一個方法裡面,甚至是一個{}塊裡面,它的作用域就在這個塊裡面:
- // 外部類
- class OutterClass {
- public void testLocalInner() {
- if (true)
- {
- class LocalInner {
- public void proc() {
- System.out.println("hello");
- }
- }
- // 可以創建使用
- LocalInner localInner = new LocalInner();
- localInner.proc();
- }
- // 錯誤:超出類定義的作用域
- LocalInner localInner = new LocalInner();
- localInner.proc();
- }
- }
局部內部類的一般用途是實現某個接口,並作為這個接口傳出方法被使用:
- // 接口
- interface Talker {
- public void Talk();
- }
- // 外部類
- class OutterClass {
- public Talker getTalker() {
- // 現實該接口的局部內部類
- class SomeTalker implements Talker {
- public void Talk() {
- System.out.println("hello");
- }
- }
- // 創建類實例並作為Talker返回
- SomeTalker talker = new SomeTalker();
- return talker;
- }
- }
- public class Main {
- public static void main(String[] args) {
- OutterClass outClass = new OutterClass();
- Talker talker = outClass.getTalker();
- talker.Talk();
- }
- }
4. 匿名內部類
匿名內部類的語法如下:
- new InterfaceName(){......}; 或 new SuperclassName(){......};
它被認為是InterfaceName的實現者,或是SuperclassName的繼承類,匿名內部類沒有構建函數,如果SuperclassName有帶參數的構造函數,必須在創建匿名內部類時帶上這些參數,下面是匿名內部類最常見的使用場合:
- // 接口
- interface Talker {
- public void Talk();
- }
- // 外部類
- class OutterClass {
- public void Talk(Talker talker) {
- talker.Talk();
- }
- }
- public class Main {
- public static void main(String[] args) {
- OutterClass outClass = new OutterClass();
- // 直接生成一個匿名內部類
- outClass.Talk(new Talker(){
- public void Talk() {
- System.out.println("hello");
- }
- });
- }
- }