1. 程式人生 > >java基礎個人筆記之抽象類,介面與多型,內部類

java基礎個人筆記之抽象類,介面與多型,內部類

抽象類:
抽象:籠統,模糊,看不懂!不具體。

特點:
1,方法只有宣告沒有實現時,該方法就是抽象方法,需要被abstract修飾。
抽象方法必須定義在抽象類中。該類必須也被abstract修飾。
2,抽象類不可以被例項化。為什麼?因為呼叫抽象方法沒意義。
3,抽象類必須有其子類覆蓋了所有的抽象方法後,該子類才可以例項化。
否則,這個子類還是抽象類。

1,抽象類中有建構函式嗎?
有,用於給子類物件進行初始化。

2,抽象類可以不定義抽象方法嗎?
可以的。 但是很少見,目的就是不讓該類建立物件。AWT的介面卡物件就是這種類。
通常這個類中的方法有方法體,但是卻沒有內容。

3,抽象關鍵字不可以和那些關鍵字共存?
private 不行
static 不行
final 不行

4,抽象類和一般類的異同點。
相同點:
抽象類和一般類都是用來描述事物的,都在內部定了成員。
不同:
1,一般類有足夠的資訊描述事物。
抽象類描述事物的資訊有可能不足。
2,一般類中不能定義抽象方法,只能定非抽象方法。
抽象類中可定義抽象方法,同時也可以定義非抽象方法。
3,一般類可以被例項化。
抽象類不可以被例項化。

5,抽象類一定是個父類嗎?
是的。因為需要子類覆蓋其方法後才可以對子類例項化。

abstract class AbsDemo
{
	abstract void show1();
	abstract void show2();
}

當一個抽象類中的方法都是抽象的時候,這時可以將該抽象類用
另一種形式定義和表示,就是 介面 interface。

//定義介面使用的關鍵字不是class,是interface.
對於介面當中常見的成員:而且這些成員都有固定的修飾符。
1,全域性常量: public static final (修飾符不寫會自動補全)
2,抽象方法。public abstract

由此得出結論,介面中的成員都是公共的許可權.

interface Demo
{
	public static final int NUM = 4;
	public abstract void show1();
	public abstract void show2();
}

//類與類之間是繼承關係,類與介面直接是實現關係。
介面不可以例項化。
只能由實現了介面的子類並覆蓋了介面中所有的抽象方法後,該子類才可以例項化。
否則,這個子類就是一個抽象類。

class DemoImpl implements /*實現*/Demo
{
	public void show1()
	{}
	public void show2()
	{
	}
}

在java中不直接支援多繼承,因為會出現呼叫的不確定性。
所以java將多繼承機制進行改良,在java中變成了多實現。
一個類可以實現多個介面。 介面的出現避免了單繼承的侷限性。

抽象類和介面的異同點:
相同點:
都是不斷向上抽取而來的。
不同點:
1,抽象類需要被繼承,而且只能單繼承。
介面需要被實現,而且可以多實現。
2,抽象類中可以定義抽象方法和非抽象方法,子類繼承後,可以直接使用非抽象方法。
介面中只能定義抽象方法,必須由子類去實現。
3,抽象類的繼承,是is a關係,在定義該體系的基本共性內容
介面的實現是 like a 關係,在定義體系額外功能
例子:犬按功能分:有導盲犬,搜爆犬。

abstract class 犬 //基本功能
{
	abstract void 吼叫();
}
interface 導盲   //額外功能
{
	abstract void 導盲();
}
class 導盲犬 extends 犬 implements 導盲
{
	public void 吼叫()
	{
	}
	public void 導盲(){}
}

物件的多型性。

class 動物
{}

class 貓 extends 動物
{}

class 狗 extends 動物
{}


貓 x = new 貓();

動物 x = new 貓();//一個物件,兩種形態。

貓這類事物即具備者貓的形態,又具備著動物的形態。
這就是物件的多型性。

簡單說:就是一個物件對應著不同型別.

多型在程式碼中的體現:
父類或者介面的引用指向其子類的物件。

多型的好處:
提高了程式碼的擴充套件性,前期定義的程式碼可以使用後期的內容。

多型的弊端:
前期定義的內容不能使用(呼叫)後期子類的特有內容。

多型的前提:
1,必須有關係,繼承,實現。
2,要有覆蓋。

畢老師和畢姥爺的故事。

class 畢姥爺
{
	void 講課()
	{
		System.out.println("管理");
	}
	void 釣魚()
	{
		System.out.println("釣魚");
	}
}

class 畢老師 extends 畢姥爺
{
	void 講課()
	{
		System.out.println("Java");
	}
	void 看電影()
	{
		System.out.println("看電影");
	}
}

class  DuoTaiDemo2
{
	public static void main(String[] args) 
	{
//		畢老師 x = new 畢老師();
//		x.講課();
//		x.看電影();

		畢姥爺 x = new 畢老師();//多型,自動型別提升,老師物件提升了姥爺型別。但是隻能訪問畢姥爺的方法(外部看到的是畢姥爺(本身是畢老師),若畢姥爺和畢老師有方法一樣,使用的是畢老師的方法),無法使用畢老師特有的方法。
		//作用就是限制對特有功能的訪問。
		//專業講:向上轉型。將子型別隱藏。就不用使用子類的特有方法。

		x.講課();
		x.釣魚();
		
		畢老師 y = (畢老師)x;//如果想用畢老師的特有功能,你可以將該物件進行向下轉型。
		//向下轉型的目的是為了使用子類中的特有方法。
//		注意:對於轉型,自始自終都是子類物件在做著型別的變化。
		y.看電影();
	}
}

//a instanceof People//instanceof:用於判斷物件的具體型別。只能用於引用資料型別判斷 //通常在向下轉型前用於健壯性的判斷。

多型時
成員的特點:
1,成員變數。
編譯時:參考引用型變數所屬的類中的是否有呼叫的成員變數,有,編譯通過,沒有,編譯失敗。
執行時:參考引用型變數所屬的類中的是否有呼叫的成員變數,並執行該所屬類中的成員變數。
簡單說:編譯和執行都參考等號的左邊。

2,成員函式(非靜態)。
編譯時:參考引用型變數所屬的類中的是否有呼叫的函式。有,編譯通過,沒有,編譯失敗。
執行時:參考的是物件所屬的類中是否有呼叫的函式。
簡單說:編譯看左邊,執行看右邊。

因為成員函式存在覆蓋特性。

3,靜態函式。
編譯時:參考引用型變數所屬的類中的是否有呼叫的靜態方法。
執行時:參考引用型變數所屬的類中的是否有呼叫的靜態方法。
簡單說,編譯和執行都看左邊。

	其實對於靜態方法,是不需要物件的。直接用類名呼叫即可。

內部類訪問特點:
1,內部類可以直接訪問外部類中的成員。
為什麼內部類能直接訪問外部類中成員呢?
那是因為內部類持有了外部類的引用。 外部類名.this
2,外部類要訪問內部類,必須建立內部類的物件。

一般用於類的設計。
分析事物時,發現該事物描述中還有事物,而且這個事物還在訪問被描述事物的內容。
這時就是還有的事物定義成內部類來描述。

class InnerClassDemo
{
	public static void main(String[] args) 
	{
//		Outer out = new Outer();
//		out.method();
		//直接訪問外部類中的內部類中的成員。
//		Outer.Inner in = new Outer().new Inner();
//		in.show();

		//如果內部類是靜態的。 相當於一個外部類
//		Outer.Inner in = new Outer.Inner();
//		in.show();

//static void function()//如果內部類中定義了靜態成員,該內部類也必須是靜態的。
//如果內部類是靜態的,成員也得是靜態的。
//		Outer.Inner.function();
		
	}
}

內部類可以存放在區域性位置上。
內部類在區域性位置上只能訪問區域性中被final修飾的區域性變數。

class Outer
{
	int num = 3;
	Object method()
	{

		final int x = 9;

		class Inner
		{
			public String toString()
			{
				return "show ..."+x;//內部類在區域性位置上只能訪問區域性中被final修飾的區域性變數。
			}
		}

		Object in = new Inner();
		return in;//0x0045
//		in.show();
	}


	
}

class InnerClassDemo3 
{
	public static void main(String[] args) 
	{
		Outer out = new Outer();
		Object obj = out.method();
		System.out.println(obj);
	}
}
/*

class Fu extends Object
{}
class zi extends Fu
{}

Fu f = new zi();

Object o = new Fu();

匿名內部類。就是內部類的簡寫格式。

必須有前提:
內部類必須繼承或者實現一個外部類或者介面。

匿名內部類:其實就是一個匿名子類物件。

格式:new 父類or介面(){子類內容}
通常的使用場景之一:
當函式引數是介面型別時,而且介面中的方法不超過三個。
可以用匿名內部類作為實際引數進行傳遞

class Outer
{
	void method()
	{
		/*new Object()
		{
			public void show()
			{
				System.out.println("show run");
			}
		}.show()//執行通過;*/
		
		Object obj = new Object()
		{
			public void show()
			{
				System.out.println("show run");
			}
		};
		obj.show();//因為匿名內部類這個子類物件被向上轉型為了Object型別。
					//這樣就不能在使用子類特有的方法了。obj沒有show方法
	}
}

class InnerClassDemo6 
{
	public static void main(String[] args) 
	{
		new Outer().method();
	}
}

例項化物件執行的順序::首先執行建構函式中預設的super()父類初始化父類=》然後初始化當前物件=》最後執行建構函式中的程式碼