為什么要用到內部類:
在java開發學習中我們經常會碰到內部類。內部類又有很多的優勢:首先舉一個簡單的例子,如果你想實現一個接口,但是這個接口中的一個方法和你構想的這個類中的一個方法名稱參數相同,你應該怎么辦?這時候,你可以建一個內部類實現這個接口。由於內部類對外部類的所有內容都是可訪問的,所以這樣做可以完成所有你直接實現這個接口的功能。不過你可能要質疑,更改一下方法的不就行了嗎?的確,以此作為設計內部類的理由,實在沒有說服力。真正的原因是這樣的,java中的內部類和接口加在一起,從而java 通過內部類加上接口,可以很好的實現多繼承的效果。
內部類的分類和使用
1、成員內部類: 即作為外部類的一個成員存在,與外部類的屬性、方法並列。注意:成員內部類中不能定義靜態變量,但可以訪問外部類的所有成員。值得注意的是成員內部類編譯成功后會生成的兩個不同的類(.class)
成員內部類的優點:
1)、內部類作為外部類的成員,可以訪問外部類的私有成員或屬性。(即使將外部類聲明為PRIVATE,但是對於處於其內部的內部類還是可見的。)
2)、用內部類定義在外部類中不可訪問的屬性。這樣就在外部類中實現了比外部類的private還要小的訪問權限。
package one; public class Outer{ private static int outer_i = 1; private int k=20; public static void outer1(){ //... } //成員內部類 class Inner{ int j=100;//內部類中外部類的實例變量可以共存 int inner_i=1; void inner1(){ System.out.println(outer_i);//外部類的變量如果和內部類的變量沒有同名的,則可以直接用變量名訪問外部類的變量 System.out.println(j);//在內部類中訪問內部類自己的變量直接用變量名 System.out.println(this.j);//也可以在內部類中用"this.變量名"來訪問內部類變量 //訪問外部類中與內部類同名的實例變量可用"外部類名.this.變量名"。 System.out.println(k);//外部類的變量如果和內部類的變量沒有同名的,則可以直接用變量名訪問外部類的變量 outer1(); } } //外部類的非靜態方法訪問成員內部類 public void outer2(){ Inner inner = new Inner(); inner.inner1(); } //外部類的靜態方法訪問成員內部類,與在外部類外部訪問成員內部類一樣 public static void outer3(){ Outer out = new Outer();//step1 建立外部類對象 Inner inner=out.new Inner();//step2 根據外部類對象建立內部類對象 inner.inner1();//step3 訪問內部類的方法 } public static void main(String[] args){ outer3(); } }
2、局部內部類: 即在方法中定義的內部類,與局部變量類似,在局部內部類前不加修飾符public或private,其范圍為定義它的代碼塊。
public class Outer { public void say(){ System.out.println("關門說真話!"); } }
public class Test { public void ting(){ class MiMi extends Outer{//定義一個局部的內部類,繼承Outer方法 //…… } new MiMi().say();//調用局部內部類中繼承的say方法 System.out.println("別人都不知道"); } public static void main(String[] args) { new Test().ting(); } }
3、靜態內部類: 靜態內部類定義在類中,任何方法外,用static定義。注意:靜態內部類中可以定義靜態或者非靜態的成員
package three; public class StaticTest { private static String name="abc"; private String sex="男"; static class Person{ private String age = "18";//內部私有成員 public String heigth = "180";//內部類公有成員 public void display(){ //System.out.println(sex);//報錯,不能直接訪問外部類的非靜態成員 System.out.println(name);//只能直接訪問外部類的靜態成員 System.out.println(age);//訪問本內部類成員。 } } public void testone(){ Person person = new Person(); person.display(); //System.out.println(heigth);//報錯,是因為不可以直接訪問內部類私有成員 //System.out.println(age);//報錯,是因為不可以直接訪問內部類公有成員 System.out.println(person.age);//可以訪問內部類的私有成員 System.out.println(person.heigth);//可以訪問內部類的公有成員 } public void testtwo(){ StaticTest st = new StaticTest(); System.out.println(name); System.out.println(sex); //System.out.println(age);//不可以直接訪問內部類的成員 //System.out.println(heigth);//不可以直接訪問內部類的成員 } public static void main(String[] args) { //調用StaticTest StaticTest staticTest = new StaticTest(); staticTest.testone(); staticTest.testtwo(); } }
4、匿名內部類: 匿名內部類是在抽象類和接口的基礎之上發展起來的。匿名內部類如果繼承自接口,必須實現指定接口的方法,且無參數 。匿名內部類如果繼承自類,參數必須按父類的構造函數的參數傳遞
匿名內部類的特點:
1),一個類用於繼承其他類或是實現接口,並不需要增加額外的方法,只是對繼承方法的事先或是覆蓋。
2),只是為了獲得一個對象實例,不需要知道其實際類型。
3),類名沒有意義,也就是不需要使用到。
package three; abstract class parent { public abstract void like(); } public class Demo { public static void main(String[] args) { parent pt = new parent(){ public void like(){ System.out.println("吃飯睡覺打豆豆。。。"); } }; pt.like(); } }
匿名類與內部的聯系與區別:
按所在位置可以分為兩大類:
1、在類的方法中
特點:
a、可以訪問宿主類的所有元素 ;
b、保存宿主類對象的引用,創建對象時必須有宿主類對象;
c、 不能有靜態數據;
繼續划分:
A、本地內部類;
B、匿名內部類
兩者的區別在於本地內部類有構造方法,而匿名內部類只能實例初始化;
2、在類或接口作用域中;
A、普通內部類
B、靜態內部類
內部類總結:
1.內部類作為外部類的一個特殊的成員來看待,因此它有類成員的封閉等級:private ,protected,默認(friendly),public 它有類成員的修飾符: static,final,abstract
2.非靜態內部類nested inner class,內部類隱含有一個外部類的指針this,因此,它可以訪問外部類的一切資源(當然包括private)外部類訪問內部類的成員,先要取得內部類的對象,並且取決於內部類成員的封裝等級。非靜態內部類不能包含任何static成員.
3.靜態內部類:static inner class,不再包含外部類的this指針,並且在外部類裝載時初始化. 靜態內部類只能訪問外部類static成員. 外部類訪問靜態內部類的成員:static成員:類名.成員;非static成員:對象.成員
4.對於方法中的內部類或塊中內部類只能訪問塊中或方法中的final變量。