1.什麼是内部類,為什麼要用内部類?
如果一個事物的内部包含另一個事物,那麼這就是一個類内部包含另一個類。
例如:身體和心髒的關系。汽車和發動機的關系。
可以将一個類定義在另一個類的定義内部,這就是内部類。
當描述事物時,事物的内部還有事物,該事物用内部類來描述,因為内部事物在使用外部事物的内容。
如:
class Body{
private class XinZang{//将這個内部類封裝起來,對外界提供通路方式
void move(){}
};
}
public void show(){
new XinZang().move();//調用其功能方法
}
2.内部類的分類
(1)成員内部類
(2)局部内部類(包含匿名内部類)
- 成員内部類的定義格式
修飾符 class 外部類名稱 {
修飾符 class 内部類名稱 {
// ...
}
// ...
}
注意:内用外,可以随意通路;外用内,需要借助内部類對象。
對于這種既有外部class,也有内部class,編譯後的.class檔案是什麼樣的?
如何使用成員内部類?有兩種方式:
- 間接方式:在外部類的方法當中,使用内部類;然後main隻是調用外部類的方法
運作結果:
- 直接方式:
公式:
一般都是 類名稱 對象名 = new 類名稱();
現在是這樣:外部類名稱.内部類名稱 對象名 = new 外部類名稱(). new 内部類名稱();
3.内部類的同名變量通路
如果出現了重名現象,格式:外部類名稱.this.外部類的成員變量名
5.局部内部類
如果一個類定義在一個方法内部的,那麼這就是一個局部内部類
“局部”:隻有目前所屬的方法才能使用它,出了這個方法外面就不能用了。
定義格式:
修飾符 傳回值類型 外部類的方法名稱(參數清單) {
class 局部内部類名稱 {
// ...
}
6.類的權限修飾符
public > protected > (default) > private
定義一個類的時候,權限修飾符規則:
(1)外部類:public / (default)
(2)成員内部類:public / protected / (default) / private
(3)局部内部類:什麼都不能寫
7.局部内部類的final問題
局部内部類,如果希望通路所在方法的局部變量,那麼這個局部變量必須是【有效final的】
備注:
從Java 8+ 開始,隻要局部變量事實不變,那麼final關鍵字可以省略。
原因:
(1)new 出來的對象在堆記憶體中
(2)局部變量是跟着方法走的,在棧記憶體中
(3)方法運作結束之後,立刻出棧,局部變量就會立刻消失
(4)但是new出來的對象會在堆中持續存在,直到垃圾回收消失
(5)是以,局部變量,和 new出來的對象生命周期不一樣,必須保證局部變量不能變。
8.匿名内部類(重點)
如果接口的實作類,或者是父類的子類,隻需要使用唯一的一次,那麼這種情況下就可以省略掉該類的定義,而改為使用【匿名内部類】
匿名内部類的定義格式:
接口名稱 對象名 = new 接口名稱() {
// 覆寫重寫所有抽象方法
};
不需要寫實作類了
圖中畫框的就是匿名内部類
對格式"new 接口名稱() {...}"進行解析:
(1)new代表建立對象的動作
(2)接口名稱就是匿名内部類需要實作哪個接口
(3){...}這才是匿名内部類的内容
匿名内部類适用于什麼樣的場景?
這個類隻想用一次,建立對象的時候用,之後再也不用了,這種情況下,可以使用匿名内部類
匿名内部類注意事項:
(1)匿名内部類,在建立對象的時候,隻能使用唯一一次。
如果希望多次建立對象,而且類的内容一樣的話,那麼就必須使用單獨定義的實作類了。
注意:匿名内部類省略的是類名,但不是匿名對象,對象名稱就叫objA
(2)匿名對象,在調用方法的時候,隻能調用唯一一次
如果希望同一個對象,調用多次方法,那麼必須給對象起個名字
(3)匿名内部類是省略了【實作類/子類名稱】,匿名對象是省略了【對象名稱】
這兩個不是一回事!!!
9.内部類的通路規則
(1)内部類可以直接通路外部類中的成員,包括私有。
之是以可以直接通路,是因為内部類中持有了一個外部類的引用,格式:外部類名.this
(2)外部類要通路内部類,必須要建立内部類的對象。
(3)在外部其他類中通路内部類的方式
Outer.Inner in=new Outer().new Inner();
class Outer{//外部類
private int x=3;
class Inner{//内部類
void function(){
System.out.println("inner"+x);
}
}
void method(){
Inner in =new Inner();
in.function();//要想通路内部類中的function方法,必須建立内部類對象
}
}
class InnerClassDemo{//外部其他類
public static void main(String[] args){
Outer out=new Outer();
out.method();
//在外部其他類中通路内部類的方式
Outer.Inner in=new Outer().new Inner();
in.function();
}
}
(4)在外部其他類中,如何直接通路static内部類的非靜态成員?
new Outer.Inner().function();
(5)在外部其他類中,如何直接通路static内部類的靜态成員?
Outer.Inner.function();
注意:如果一個内部類中定義了靜态成員,那麼該内部類必須是static
class Outer{//外部類
private int x=3;
static class Inner{//内部類中定義了靜态方法,是以該内部類必須是static
static void function(){
System.out.println("inner"+x);
}
}
class Outer{//外部類
static class Inner{//内部類
void show(){
System.out.println("inner show");
}
}
public static void method(){//外部類中的靜态方法通路内部類,該内部類必須是static
new Inner().show();
}
}