內部類解說

wbw_wgl發表於2020-11-14

內部類

概念

在一個類中書寫另一個類

分類

同級類(嚴格意義上來講只是一種書寫形式不是內部類)

成員內部類(全域性內部類)

區域性內部類(包含匿名內部類)

①同級類

在當前類同級下繼續書寫其他類,書寫語法與普通類相同,但修飾符只能使用預設

在使用時與普通類一致,只是訪問範圍只有本包下,將相當於少建立了一個檔案

//員工類
public abstract class Employee {
	public String name;// 姓名
	public int birthdayMonth;// 生日月份
	public double salary;// 薪資

	public abstract void getSalary(int month);

}

// 同級類的形式
class sale extends Employee {
	public double saleMoney;// 銷售額
	public double rate;// 提成率

	@Override
	public void getSalary(int month) {	
		salary+=saleMoney*rate;
		if(birthdayMonth==month){
			salary+=100;
		}
		System.out.println("銷售員"+name+month+"月份的工資為:"+salary);
	}
}

②成員內部類(全域性內部類)

書寫在類體中的類

修飾符 class 類名稱 {
    修飾符 class 類名稱 {
        //...
    }
    //...
}
public class A {
	int aa;
	// 成員內部類
	// 在一個類中書寫另一個類
	public class B { 
		// 內部類可以隨意訪問外部類(包含其他外部類)
		public void b() {
			// 直接訪問當前外部類
			A a = new A();
			// 可以直接訪問其他外部類
			A1 a1 = new A1();
			int b=A.this.a;//內部類可以直接使用外部類的屬性
			//由於就近原則當出現屬性與外部類相同時,使用語法
			//外部類.this.屬性名進行指定
		}
	}

	public void a() {
		B b = new B();
		b.b();
	}
}

class A1 {
	// 內部類的呼叫
	public static void main(String[] args) {
		// 1、間接呼叫
		// 其他外部類不能直接訪問但是書寫內部類的外部類可以訪問
		// 在外部類宣告方法建立內部類物件呼叫方法
		// 在其他類中建立外部類呼叫內部類方法
		A a = new A();
		a.a();// 實際呼叫內部類b方法
		// 2、直接呼叫
		//直接在其他外部類建立內部類物件
		//語法:外部類.內部類 識別符號 =new 外部類().new 內部類();
		A.B b=new A().new B();
		//可以將內部類當做變數,如果想獲取一個類的成員變數那麼必須先建立這個類的物件
		//之後因為是一個類 如果想使用必須建立物件
		b.b();//直接使用B物件呼叫b方法
	}

}

成員內部類總結:

1、書寫在類體中的類

2、只能由當前類的外部類直接訪問

3、可以直接訪問外部類(其他外部類)

4、使用同名外部類變數時注意語法 外部類.this.屬性名

5、其他外部類訪問方式 間接方式(建立外部類通過外部類方法使用內部類) 直接方式(通過外部類直接建立內部類物件)

③區域性內部類

如果類是定義在一個方法內部的,那麼這就是一個區域性內部類。

“區域性”:只有當前所屬的方法才能使用它,出了這個方法外面就不能用了。

修飾符 class 外部類名稱 {
    修飾符 返回值型別  外部類方法名稱(引數列表) {
        class 區域性內部類名稱 {
            //...
        }
    }
}
public class B {
	int b = 1;

	// 區域性內部類
	// 在方法體中定義的類
	public void b() {
		int b = 2;
		// 由於方法中變數在方法執行結束後會釋放
		// 並且只能由當前方法呼叫,所以修飾符不能使用public
		class C {
			int c = 3;

			public void c() {
				System.out.println(c);
				System.out.println(b);// 可以直接使用方法中的變數
				System.out.println(B.this.b);// 通過固定語法訪問同名全域性變數
				// 當區域性內部類使用方法中的變數時,一般使用final修飾
				// 由於其資料儲存空間不同,在執行時可能導致錯誤
				// 1. new 出來的物件在堆記憶體當中。
				// 2. 區域性變數是跟著方法走的,在棧記憶體當中。
				// 3. 方法執行結束後,立刻出棧,區域性變數就會立刻消失。
				// 4. 但是new出來的物件在堆當中持續存在,直到垃圾回收消失。

			}
		}
		C c = new C();
		c.c();
	}

	public void b1() {
		// 其他方法不能呼叫區域性內部類,只能通過間接呼叫
	}

	public static void main(String[] args) {
		B b = new B();
		b.b();
	}
}

區域性內部類總結:

1、書寫在方法體中的類

2、只能由當前方法直接訪問

3、可以直接訪問外部類(其他外部類)

4、使用同名方法所在類變數時注意語法 外部類.this.屬性名(對於方法中同名屬性不能直接呼叫建議改名)

5、其他外部類(方法)訪問方式 間接方式(通過訪問方法的形式進行呼叫)

6、區域性內部類使用方法中變數的值實際過程是建立空間將值複製過來進行使用,要求變數理論不變的原因,是因為回收時機不同,可能導致程式錯誤(區域性內部類不建議使用方法中的屬性進行屬性的賦值)

修飾內部類的許可權

public > protected > (default) > private

定義一個類的時候,許可權修飾符規則:

外部類:public / (default)

成員內部類:都可以寫,public > protected > (default) > private

區域性內部類:什麼都不能寫,但不是default

匿名內部類

屬於區域性內部類,書寫在方法中但建立類無需類名與class關鍵字,只需要書寫方法體{}

如果介面的實現類(或者是父類的子類)只需要使用唯一的一次。

那麼這種情況下就可以省略調該類的定義,而改為使用【匿名內部類】。

匿名內部類用於建立子類或者實現類

介面(父類) 物件名 = new 類名或者介面名稱() {
    //覆蓋重寫所有抽象方法
};
public interface C {
	void a();
	void b();
	void c();
}

class Test{
	public static void main(String[] args) {
		//匿名內部類就是省略類的宣告與命名只書寫類體{}
		//一般用於只使用一次的子類或實現類
		C c=new C(){
			@Override
			public void a() {
				System.out.println("a");
			}
			@Override
			public void b() {
				System.out.println("b");
			}
			@Override
			public void c() {
				System.out.println("c");
			}
		};
		//會直接使用匿名內部類建立一個唯一物件
		//這個物件只有一個,因為沒有類
		//相當於使用類體臨時建立了一個類並用其建立物件	
		c.a();
	}
}

匿名物件:

建立的物件只呼叫一次方法那麼可以直接使用new 類名().方法()進行使用

注意:

匿名物件與匿名內部類不是同一個東西

匿名物件省略了類的宣告

匿名內部類省略了class關鍵字以及類名

匿名內部類總結

1、匿名內部類由於沒有建立類,所以使用父類或者介面宣告變數儲存遵循多型,只能使用重寫的方法以及父類的屬性,但是重寫的方法可以使用這些屬性,只不過不能通過物件進行賦值,(一般在使用匿名內部類的時候不會建立屬性只重寫方法)

方法呼叫總結:
1.內部類可以建立外部類物件掉用外部類方法;
2.外部類呼叫內部類方法有2種;
①間接呼叫:建立外部類通過外部類方法使用內部類
例如:同部類A,同部類A1,實現同級類A1呼叫同級類A中的內部類方法b.
步驟:在同級類A中建立方法a,方法裡建立內部類物件並呼叫內部類方法;
在同級類A1中,建立同級類A的物件,該物件呼叫建立的方法a.

public class A {
int a;


	public class B { 
	int b;
		public void b() {
		int c;
		}
	}

	public void a() {
		B b = new B();
		b.b();
	}
}

class A1 {
	// 內部類的呼叫
	public static void main(String[] args) {
		// 1、間接呼叫
		// 其他外部類不能直接訪問但是書寫內部類的外部類可以訪問
		// 在外部類宣告方法建立內部類物件呼叫方法
		// 在其他類中建立外部類呼叫內部類方法
		A a = new A();
		a.a();// 實際呼叫內部類b方法
		// 2、直接呼叫
		//直接在其他外部類建立內部類物件
		//語法:外部類.內部類 識別符號 =new 外部類().new 內部類();
		A.B b=new A().new B();
		//可以將內部類當做變數,如果想獲取一個類的成員變數那麼必須先建立這個類的物件
		//之後因為是一個類 如果想使用必須建立物件
		b.b();//直接使用B物件呼叫b方法
	}

}

直接呼叫:通過外部類直接建立內部類物件
語法:

外部類名稱(要呼叫的).內部類名稱  物件名=new 外部類名稱().new內部類名稱();
A.B b=new A().newB();
b.b();

屬性呼叫:
類重名情況;
呼叫內部類方法的屬性c;
把內部類方法的b賦值給內部類的屬性:this.c;
把內部類方法的的屬性賦值給外部類的屬性:A.this.b(語法:外部類.this.屬性名)

相關文章