一、什么是內部類?
內部類是指在一個外部類的內部再定義一個類。內部類作為外部類的一個成員,並且依附於外部類而存在的。內部類可為靜態,可用protected和private修飾(而外部類只能使用public和缺省的包訪問權限)。
內部類主要有一下幾種:成員內部類、局部內部類、靜態內部類、匿名內部類。
二、內部類的共性:
(1)、內部類仍然是一個獨立的類,在編譯之后內部類會被編譯成獨立的.class文件,但是前面冠以外部類的類名和$符號 。
(2)、內部類不能用普通的方式訪問。
(3)、內部類聲明成靜態的,就不能隨便的訪問外部類的成員變量了,此時內部類只能訪問外部類的靜態成員變量 。
(4)、外部類不能直接訪問內部類的的成員,但可以通過內部類對象來訪問
三、為什么需要內部類?
其主要原因有以下幾點:
1、內部類方法可以訪問該類定義所在的作用域的數據,包括私有的數據
2、內部類可以對同一個包中的其他類隱藏起來,一般的非內部類,是不允許有 private 與protected權限的,但內部類可以
3、可以實現多重繼承
4、當想要定義一個回調函數且不想編寫大量代碼時,使用匿名內部類比較便捷
使用內部類最吸引人的原因是:
每個內部類都能獨立地繼承自一個(接口的)實現,所以無論外圍類是否已經繼承了某個(接口的)實現,對於內部類都沒有影響。大家都知道Java只能繼承一個類,它的多重繼承在我們沒有學習內部類之前是用接口來實現的。但使用接口有時候有很多不方便的地方。比如我們實現一個接口就必須實現它里面的所有方法。而有了內部類就不一樣了。它可以使我們的類繼承多個具體類或抽象類。
四、代碼實現
1、成員內部類
即在一個類中直接定義的內部類,成員內部類與普通類的成員沒什么區別,可以與普通成員一樣進行修飾和限制。成員內部類不能含有static的變量和方法。
package com.test; public class Outer { private static int number = 100; private int j = 20; private String name = "Java"; public static void outer_funOne(){ System.out.println("外部類Outer的靜態方法:outer_funOne"); } public void outer_funTwo(){ System.out.println("外部類的普通方法:outer_funTwo"); } //成員內部類,可以訪問外部類的所有成員 class Demo{ //內部類不允許定義靜態變量 //static int demo_i = 100; int j =50; //內部類和外部類的實例變量可以共存 //成員內部類中的方法定義 public void demo_funOne(){ //內部類中訪問內部類自己的變量直接用變量名 //也可以用 this.j System.out.println(j); //內部類中訪問外部類的成員變量語法:外部類類名.this.變量名 System.out.println("內部類訪問外部類變量:"+Outer.this.j); //如果內部類中沒有與外部類中有相同的變量,則可以直接用變量名使用 System.out.println(name); //內部類調用外部類方法 outer_funOne(); //靜態方法 outer_funTwo(); //非靜態方法 } } public static void outer_funThree(){ //外部類靜態方法訪問成員內部類 // 1、建立外部類對象 Outer out = new Outer(); // 2、根據外部類建立內部類對象 Demo demo = out.new Demo(); // 訪問內部類方法 demo.demo_funOne(); //訪問內部類字段 System.out.println("內部類成員字段:"+demo.j); } public static void main(String[] args) { //調用內部類的方法 // 1、創建外部類對象 Outer out = new Outer(); // 2、通過外部類對象創建內部類對象 Outer.Demo demo = out.new Demo(); // 1、2步簡寫 // Outer.Demo demo1 = new Outer().new Demo(); //方法調用 demo.demo_funOne(); } }
結果:
2、局部內部類
在方法中定義的內部類稱為局部內部類。與局部變量類似,局部內部類不能有訪問說明符,因為它不是外圍類的一部分,但是它可以訪問當前代碼塊內的常量,和此外圍類所有的成員。
需要注意的是:
(1)、局部內部類只能在定義該內部類的方法內實例化,不可以在此方法外對其實例化。
(2)、局部內部類對象不能使用該內部類所在方法的非final局部變量。
package com.test; public class Outer { private static int number = 100; private int j = 20; private String name = "Java"; //定義外部類方法 public void outer_funOne(int k){ final int number = 100; int j = 50; //方法內部的類(局部內部類) class Demo{ public Demo(int k){ demo_funOne(k); } int number = 300; //可以定義與外部類同名的變量 // static int j = 10; //不可以定義靜態變量 //內部類的方法 public void demo_funOne(int k){ System.out.println("內部類方法:demo_funOne"); //訪問外部類的變量,如果沒有與內部類同名的變量,則可直接用變量名 System.out.println(name); //訪問外部類與內部類同名的變量 System.out.println(Outer.this.number); System.out.println("內部類方法傳入的參數是:"+k); } } new Demo(k); } public static void main(String[] args) { //訪問內部類必須要先有外部類對象 Outer out = new Outer(); out.outer_funOne(11); } }
結果:
3、靜態內部類(嵌套類)
如果你不需要內部類對象與其外圍類對象之間有聯系,那你可以將內部類聲明為static。這通常稱為嵌套類(nested class)。想要理解static應用於內部類時的含義,你就必須記住,普通的內部類對象隱含地保存了一個引用,指向創建它的外圍類對象。然而,當內部類是static的時,就不是這樣了。嵌套類意味着:
1. 要創建嵌套類的對象,並不需要其外圍類的對象。
2. 不能從嵌套類的對象中訪問非靜態的外圍類對象。
package com.test; public class Outer { private static int number = 100; private int j = 20; private String name = "Java"; public static void outer_funOne(){ System.out.println("外部類靜態方法:outer_funOne"); } public void outer_funTwo(){ } //靜態內部類可以用public、protected、private修飾 //靜態內部類可以定義靜態類或非靜態內部類 private static class Demo{ static int j = 100; String name = "C#"; //靜態內部類里的靜態方法 static void demo_funOne(){ //靜態內部類只能訪問外部類的靜態成員(靜態變量、靜態方法) System.out.println("靜態內部類訪問外部類靜態變量:"+number); outer_funOne();//訪問外部類靜態方法 } //靜態內部類非靜態方法 void demo_funTwo(){ } } public void outer_funThree(){ //外部類訪問內部類靜態成員:內部類.靜態成員 System.out.println(Demo.j); //訪問靜態方法 Demo.demo_funOne(); //訪問靜態內部類的非靜態成員,實例化內部類即可 Demo demo = new Demo(); //訪問非靜態變量 System.out.println(demo.name); //訪問非靜態方法 demo.demo_funTwo(); } public static void main(String[] args) { new Outer().outer_funThree(); } }
結果:
3、匿名內部類
1、只用到類的一個實例。
2、類在定義后馬上用到。
3、類非常小(SUN推薦是在4行代碼以下)
4、給類命名並不會導致你的代碼更容易被理解。
代碼。。。。。。。。