天天看點

内部類

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();
		
	}
}
      

繼續閱讀