1. 程式人生 > >JavaSE學習筆記(3.Java類的介紹)

JavaSE學習筆記(3.Java類的介紹)

1.類的成員:

類的成員包括:構造器、類成員變數、例項成員變數、類方法、例項方法、類初始化塊、例項初始化塊

2.構造器描述:

a.構造器名必須與類名相同,在類的例項化過程中,需要呼叫構造器,如果類沒有構造器,系統會預設提供一個預設的無參構造器。

b.構造器不能定義返回型別(包括void型別),如果構造器存在返回型別,系統會將其當做一個類的方法而不是構造器!

c.構造器可支援過載

d.public修飾構造器,類可以在類內類外例項化;private修飾構造器,類只能在類內例項化(單例模式的實現依賴於這種方式

單例模式的程式碼:

public class Test {
	public static void main(String arg[]){
		Data d = Data.getInstance();
		Data d1 = Data.getInstance();
		System.out.println(d == d1);
	}
}

class Data{
	private static Data Instance = null;
	
	private Data(){
		System.out.println("Data Init");
	}
	
	public static Data getInstance()
	{
		if(null == Instance)
		{
			Instance = new Data();
		}
		
		return Instance;
	}
}

e.類例項化的過程,會預設將例項成員變數進行初始化,基本型別變數賦值為0/false,引用型別變數賦值為null

3.this物件:

a.this物件表示的是當前物件,即當前執行態執行方法或者獲取成員變數的物件,通過這個原則就可以知道當前訪問的是那個例項的成員

b.this訪問的都是例項成員,是需要例項化後才可以訪問的,所以static修飾的靜態類方法中是不可以使用this來訪問例項成員的

c.通常情況下,訪問例項成員的時候有this和沒有this是一樣的,但是當例項成員和區域性變數重名的時候,為了避免歧義就要使用this物件來區分!

d.構造器發生過載的時候,在構造器內部需要呼叫其他構造器的時候,需要使用this作為構造器名

public class Test{
	public static void main(String arg[]){
		Data d = new Data("java test");
	}
}

class Data{
	public Data()
	{
		System.out.println("Data init");
	}
	public Data(String name)
	{
		/*必須放到第一行*/
		this();
		System.out.println("Data "+name+" init");
	}
}

Ps:只有構造器中才可以呼叫構造器,而且構造器其中呼叫構造器必須放到函式第一行!

4.可變長行參:

Java1.5 引入形參可變長,格式為:【型別... 變數名】,只能放在引數列表的最後。本質就是陣列,但是入參選擇陣列形式也可以選擇可變長行參形式,具體程式碼如下:

public class Test{
	public static void main(String arg[]){
		Data d = new Data();
		/*可變引數形式*/
		d.TestFun(2,3,4,5,6);
		/*陣列形式,過載的時候只能使用陣列的形式*/
		d.TestFun(2,new int[]{3,4,5,6});
	}
}

class Data{
	public void TestFun(int a,int... b){
		for(int temp : b)
		{
			System.out.println(temp);
		}
	}
}

Ps:當使用可變長形參的時候,如果發生方法過載,必須使用陣列形式作為入參!Java的過載為,同類中方法名相同,引數列表不同,與返回值和修飾符無關!

4.類的繼承:

a.Java為單繼承,但是介面可以用來補充多繼承

b.方法重寫:

1)子類父類方法名相同,入參相同;

2)子類方法的返回值型別比父類方法的返回值型別小或者相對;

3)子類方法宣告丟擲異常類比父類方法宣告丟擲異常類小或者相等;

4)子類方法訪問許可權比父類方法訪問許可權大或者相等;

5)子類父類方法同為類方法或者同為例項方法;

Ps:與方法過載比較,方法過載發生在同一個類內,方法名相同,入參不同的時候(返回值型別、方法修飾符不參與判斷);方法重寫發生在父類子類之間,方法名相同,入參相同的時候;但是如果不滿足如上條件2、條件3、條件4、條件5,編譯會報錯!

c.方法重寫的時候,要注意儘可能的避免在父類建構函式中呼叫被重寫的方法,因為當子類構造父類的時候,子類呼叫父類的建構函式,父類建構函式中呼叫的是子類重寫後的方法(原因是因為當前執行的物件為子類物件,通過列印this物件可以看到),設計不好,容易觸發邏輯異常!

public class Test{
	public static void main(String arg[]){
		DataTemp d = new DataTemp();
	}
}

class Data{
	public Data(){
		System.out.println(this);
		test();
	}

	public void test(){
		System.out.println("Data Init");
	}

}

class DataTemp extends Data{
	public DataTemp(){
		System.out.println(this);
		test();
	}

	public void test(){
		System.out.println("DataTemp Init");
	}
}

輸出:

[email protected]
DataTemp Init
[email protected]
DataTemp Init

c.當建立一個子類物件的時候,系統不僅僅會為子類成員分配記憶體空間,同時也會為其所有父類分配記憶體空間,並且會從上至下呼叫建構函式!子類呼叫父類建構函式的順序如下:

5.super限定:

a.super限定用來獲取父類中的例項方法和例項成員變數,主要應用於方法的重寫和子父類中同名成員的覆蓋場景!

b.子類建構函式中,呼叫父類建構函式,使用super();super()也需要放在構造器中的第一行,所以super()和this()不能同時使用!

6.類的多型:

a.當一個引用變數,在編譯期型別和執行期型別不一樣的時候,就可能發生多型!

b.java引用型別預設都是向上轉換的,就是可以將子類賦值給父類;當父類賦值給子類的時候就需要強制型別轉換並且保證執行期,父類的內容就是這個子類內容,不然會丟擲異常!

c.強制型別轉換前,可以使用instanceof運算子來(if (object instanceof TYPE)),判斷前一個引數object物件是否是TYPE類或者TYPE子類的例項,進而判斷是否可以強制型別轉換成功,instanceof前後引數在編譯期必須要存在父子類關係,不然會編譯報錯!

7.初始化塊的描述:

a.初始化塊就是執行在構造器前面的一段程式碼塊,如果該程式碼塊寫在變數初始化前面,程式碼塊會在變數初始化前完成;如果程式碼塊寫在變數初始化後面,程式碼塊會改變變數初始化的值,當執行完變數初始化和初始化塊後再執行構造器;多個初始化塊會按照先後順序執行;初始化塊不存在繼承!

b.初始化塊的本質:初始化塊設計的本質就是將多個構造器中的,引數無關的公共程式碼統一處理;通過檢視class檔案可以發現,初始化塊在編譯後消失了,分別被編譯器放到每個構造器中去了!

c.staic修飾靜態類初始化塊:例項初始化塊是在物件建立的時候執行的,類初始化塊是在類建立的時候執行的,所以屬於類成員;類成員統一滿足一個原則,不能訪問例項成員,包括例項成員變數、例項方法、super、this物件!