1. 程式人生 > 其它 >JAVA面向物件學習——java面向物件概念———內部類

JAVA面向物件學習——java面向物件概念———內部類

內部類

Java從JDK 1.1開始引入內部類,內部類主要有如下作用:

➢ 內部類提供了更好的封裝,可以把內部類隱藏在外部類之內,不允許同一個包中的其他類訪問該類。

➢ 內部類成員可以直接訪問外部類的私有資料,因為內部類被當成其外部類成員,同一個類的成員之間可以互相訪問。

但外部類不能訪問內部類的實現細節,例如內部類的成員變數。

➢ 匿名內部類適合用於建立那些僅需要一次使用的類。

從語法角度來看,定義內部類與定義外部類的語法大致相同,內部類除需要定義在其他類裡面之外,還存在如下兩點區別:

➢ 內部類比外部類可以多使用三個修飾符:private、protected、static—外部類不可以使用這三個修飾符。

➢ 非靜態內部類不能擁有靜態成員。

-----------------------------------------------------------------------------------------------

------------------------------------------------------------------------------------------------

public class Cow
{
	private double weight;
	
	public Cow()                  // 外部類的兩個過載的構造器
	{
		
	}
	
	public Cow(double weight)
	{
		this.weight = weight;
	}
	
	
	private class CowLeg                 // 定義一個非靜態內部類
	{
		
		private double length;               // 非靜態內部類的兩個例項變數
		private String color;
		
		public CowLeg()                   // 非靜態內部類的兩個過載的構造器
		{
			
		}
		
		public CowLeg(double length, String color)
		{
			this.length = length;
			this.color = color;
		}
		
		public void setLength(double length)    // 下面省略length、color的setter和getter方法
		{
			this.length = length;
		}
		
		ublic double getLength()
		{
			return this.length;
		}
		
		public void setColor(String color)
		{
			this.color = color;
		}
		
		public String getColor()
		{
			return this.color;
		}
		
		public void info()   // 非靜態內部類的例項方法
		{
			System.out.println("當前牛腿顏色是:" + color + ", 高:" + length);
			
			System.out.println("本牛腿所在奶牛重:" + weight);    // 直接訪問外部類的private修飾的成員變數
		}
	}
	
	public void test()
	{
		CowLeg cl = new CowLeg(1.12, "黑白相間");
		cl.info();
	}
	
	public static void main(String[] args)
	{
		Cow cow = new Cow(378.9);
		cow.test();
	}
}

  

------------------------------------------------------------------------------------------

------------------------------------------------------------------------------------------

當在非靜態內部類的方法內訪問某個變數時,系統優先在該方法內查詢是否存在該名字的區域性變數,如果存在就使用該變數;


如果不存在,則到該方法所在的內部類中查詢是否存在該名字的成員變數,如果存在則使用該成員變數;


如果不存在,則到該內部類所在的外部類中查詢是否存在該名字的成員變數,如果存在則使用該成員變數;


如果依然不存在,系統將出現編譯錯誤:提示找不到該變數。


因此,如果外部類成員變數、內部類成員變數與內部類裡方法的區域性變數同名,則可通過使用 this、外部類類名.this 作為限定來區分。

如下程式所示。

public class DiscernVariable
{
	private String prop = "外部類的例項變數";
	
	private class InClass
	{
		private String prop = "內部類的例項變數";
public void info() { var prop = "區域性變數"; System.out.println("外部類的例項變數值:" + DiscernVariable.this.prop); // 通過 外部類類名.this.varName 訪問外部類例項變數 System.out.println("內部類的例項變數值:" + this.prop); // 通過 this.varName 訪問內部類例項的變數 System.out.println("區域性變數的值:" + prop); // 直接訪問區域性變數 } } public void test() { InClass in = new InClass(); in.info(); } public static void main(String[] args) { new DiscernVariable().test(); } }

  

執行結果:

------------------------------------------------------------------------------------------

------------------------------------------------------------------------------------------

6.7.1 非靜態內部類
內部類都被作為成員內部類定義,而不是作為區域性內部類。成員內部類是一種與成員變數、方法、構造器和初始化塊相似的類成員;區域性內部類和匿名內部類則不是類成員。

成員內部類分為兩種:靜態內部類和非靜態內部類,使用static修飾的成員內部類是靜態內部類,沒有使用static修飾的成員內部類是非靜態內部類。

成員內部類(包括靜態內部類、非靜態內部類)的class檔案總是這種形式:OuterClass$InnerClass.class。

當在非靜態內部類的方法內訪問某個變數時,系統優先在該方法內查詢是否存在該名字的區域性變數,如果存在就使用該變數;如果不存在,則到該方法所在的內部類中查詢是否存在該名字的成員變數,如果存在則使用該成員變數;如果不存在,則到該內部類所在的外部類中查詢是否存在該名字的成員變數,如果存在則使用該成員變數;如果依然不存在,系統將出現編譯錯誤:提示找不到該變數。因此,如果外部類成員變數、內部類成員變數與內部類裡方法的區域性變數同名,則可通過使用this、外部類類名.this作為限定來區分。

非靜態內部類的成員可以訪問外部類的例項成員,但反過來就不成立了。如果外部類需要訪問非靜態內部類的例項成員,則必須顯式建立非靜態內部類物件來呼叫訪問其例項成員。

根據靜態成員不能訪問非靜態成員的規則,外部類的靜態方法、靜態程式碼塊不能訪問非靜態內部類,包括不能使用非靜態內部類定義變數、建立例項等。總之,不允許在外部類的靜態成員中直接使用非靜態內部類。

Java不允許在非靜態內部類裡定義靜態成員,非靜態內部類裡不能有靜態方法、靜態成員變數、靜態初始化塊。

6.7.2 靜態內部類
靜態內部類可以包含靜態成員,也可以包含非靜態成員。根據靜態成員不能訪問非靜態成員的規則,靜態內部類不能訪問外部類的例項成員,只能訪問外部類的類成員。即使是靜態內部類的例項方法也不能訪問外部類的例項成員,只能訪問外部類的靜態成員。

6.7.3 使用內部類
1.在外部類內部使用內部類

從前面程式中可以看出,在外部類內部使用內部類時,與平常使用普通類沒有太大的區別。一樣可以直接通過內部類類名來定義變數,通過new呼叫內部類構造器來建立例項。唯一存在的一個區別是:不要在外部類的靜態成員(包括靜態方法和靜態初始化塊)中使用非靜態內部類,因為靜態成員不能訪問非靜態成員。在外部類內部定義內部類的子類與平常定義子類也沒有太大的區別。

2.在外部類以外使用非靜態內部類

如果希望在外部類以外的地方訪問內部類(包括靜態和非靜態兩種),則內部類不能使用private訪問控制權限,private修飾的內部類只能在外部類內部使用。

對於使用其他訪問控制符修飾的內部類,則能在訪問控制符對應的訪問許可權內使用:

➢ 省略訪問控制符的內部類,只能被與外部類處於同一個包中的其他類所訪問。

➢ 使用protected修飾的內部類,可被與外部類處於同一個包中的其他類和外部類的子類所訪問。

➢ 使用public修飾的內部類,可以在任何地方被訪問。

在外部類以外的地方定義內部類(包括靜態和非靜態兩種)變數的語法格式如下:

由於非靜態內部類的物件必須寄生在外部類的物件裡,因此建立非靜態內部類物件之前,必須先建立其外部類物件。在外部類以外的地方建立非靜態內部類例項的語法如下:

3.在外部類以外使用靜態內部類

因為靜態內部類是外部類類相關的,因此建立靜態內部類物件時無須建立外部類物件。在外部類以外的地方建立靜態內部類例項的語法如下:

6.7.4 區域性內部類
如果把一個內部類放在方法裡定義,則這個內部類就是一個區域性內部類,區域性內部類僅在該方法裡有效。由於區域性內部類不能在外部類的方法以外的地方使用,因此區域性內部類也不能使用訪問控制符和static修飾符修飾。

6.7.5 匿名內部類
匿名內部類適合建立那種只需要一次使用的類,定義匿名內部類的格式如下:

關於匿名內部類還有如下兩條規則:

➢ 匿名內部類不能是抽象類,因為系統在建立匿名內部類時,會立即建立匿名內部類的物件。因此不允許將匿名內部類定義成抽象類。

➢ 匿名內部類不能定義構造器。由於匿名內部類沒有類名,所以無法定義構造器,但匿名內部類可以定義初始化塊,可以通過例項初始化塊來完成構造器需要完成的事情。