內部類
在一個類中定義另外一個類,這個類就做內部類或內置類(inner class),也稱嵌套類,包含內部類的類稱爲外部類(outer class)。
- 成員類
如下例中,聲明OuterOne外部類包含內部類InnerOne。其中外部類和內部類的其他成員處於同級位置,所以稱爲成員類。
public class OuterOne {
private int x =3;
InnerOne ino = new InnerOne(); //外部類有一個屬性指向創建的內部類的對象
public class InnerOne{ //內部類
private int y =5;
public void innerMethod(){
System.out.println("y is "+y);
}
public void innerMethod2(){
System.out.println("z is "+x); //訪問外部類變量
}
} //內部類變量
public void OuterMethod(){
System.out.println("x is "+x);
ino.innerMethod();
ino.innerMethod2();
}
public static void main(String[] args) {
Learning my = new Learning();
my.OuterMethod();
}
}
運行結果:
注意:
(1)內部類的命名除了不能與自己的外部類同名外,不必擔心與其他類名衝突,因爲其真實名字上了外部類名作爲前綴。如,內部類InnerOne經過編譯後出現OuterOne$InnerOne.class。
(2)在外部類中訪問內部類一般通過在外部類的成員定義中創建內部類對象,例如:InnerOne ino = new InnerOne()。
(3)在內部類使用this,this指內部類的對象,要訪問外部類的當前對象須加上外部類名作前提。例如:上例,可用OuterOne.this代表外部類的this對象。
- 靜態內部類
定義爲static的內部類稱爲靜態類。靜態類自動轉化爲頂層類,即沒有父類,而且不能引用外部類成員或其他內部類成員。且只有靜態內部類才能聲明靜態成員。
public class StaticEg {
public static class Person{ //聲明一個靜態的、公用的內部類。
private int age;
private String name;
static int count = 0; //聲明一個靜態變量
Person(String n,int a){
name = n;
age = a;
count++;
}
public void display(){
System.out.println("count=" +count +"\t\t" +name +"\t\t" + age);
}
}
public static void main(String[] args) {
StaticEg.Person p1 = new StaticEg.Person("小易", 14);
p1.display();
StaticEg.Person p2 = new StaticEg.Person("千千", 15);
p2.display();
StaticEg.Person p3 = new StaticEg.Person("小舞", 16);
p3.display();
}
}
運行結果:
- 局部內部類:
Java內部類也可以是局部的,它可以定義在一個方法甚至一個代碼塊之內。
public class PartEg {
public static void main(String[] args) {
final int i = 8; //定義一個final類型的局部變量。
class person {
public String name;
public void show() { //內部類方法
System.out.println(i);
System.out.println(this.name);
}
}
person p = new person();
p.name = "Jackson";
p.show();
}
}
運行結果:
方法中內部類只能訪問方法中的final類型的局部變量,而不能訪問其他類型的局部變量,但可以訪問部類的所有數據成員和成員方法。
- 匿名內部類
Java允許創建對象的同時定義類的實現,但是未規定類名,Java將其定義爲匿名內部類。適用情況:只需創建一個 類的對象並且用不上它的名字時,或者說有的內部類只需要創建一個它的對象,以後不會用到這個類。
語法規則:
new interfacename(){...};
或 new superclassname(){...};
實例:
方法count()使用匿名內部類直接返回了一個實現了接口Contents的類的對象。
public interface Contents {
int value();
}
public class Test1 {
public Contents cont(){
return new Contents(){ //返回值的生成及表示返回值的類的定義
private int i = 11;
public int value(){
return i;
}
}; //分號
}
}
注意:
匿名內部類因爲沒有名字,所以她沒有構造方法。但如果該匿名內部類繼承了一個只含有帶參數構造方法的父類,創建它的時候就必須帶上這些參數,並在實現過程中使用super關鍵字調用相應內容。
如果要初始化它的數據成員,可採用下面幾種方法:
(1)如果是一個方法的匿名內部類,通過這個方法傳進需要的參數,同時這些參數不許被聲明爲final。
(2)將匿名內部類改造成有名字的局部內部類,這樣這個類就可以擁有構造方法了。
(3)在匿名內部類中使用初始化代碼塊。