1. 程式人生 > >Java 面向物件之構造方法

Java 面向物件之構造方法

01構造方法引入
  A:構造方法的引入
    在開發中經常需要在建立物件的同時明確物件的屬性值,比如員工入職公司就要明確他的姓名、年齡等屬性資訊。
    那麼,建立物件就要明確屬性值,那怎麼解決呢?也就是在建立物件的時候就要做的事情,當使用new關鍵字建立物件時,怎麼給物件的屬性初始化值呢?
    這就要學習Java另外一門小技術,構造方法。
  B: 那什麼是構造方法呢?
    從字面上理解即為構建創造時用的方法,即就是物件建立時要執行的方法。既然是物件建立時要執行的方法,那麼只要在new物件時,
    知道其執行的構造方法是什麼,就可以在執行這個方法的時候給物件進行屬性賦值。

02構造方法作用
  A: 構造方法的作用:     在new的同時給成員變數賦值,給物件屬性進行初始化。   B: 舉例:     Perons p = new Person("張三",23); 在new 的時候給p物件的name屬性和age屬性進行賦值,使這個物件的屬性有值。 03構造方法的定義和執行特點   A: 構造方法定義   構造方法的格式:   修飾符 構造方法名(引數列表) { }   B: 構造方法的體現:   構造方法沒有返回值型別。也不需要寫返回值。因為它是為構建物件的,物件建立完,方法就執行結束。   構造方法名稱必須和型別保持一致。   構造方法沒有具體的返回值。   構造方法的程式碼體現:   C: 構造方法舉例   class Person {     // Person的成員屬性age和name     private int age;     private String name;     // Person的構造方法,擁有引數列表     Person(int a, String nm) {     // 接受到建立物件時傳遞進來的值,將值賦給成員屬性     age = a;     name = nm;   }   }   D: 構造方法執行特點:     在new 物件的時候自動呼叫執行。 04預設新增的構造方法
  A: 每一class類都必須有一個構造方法,構造方法不寫也有。     編譯的時候,javac,系統會自動檢查類中是否有構造方法,如果沒有編譯器就會自動新增一個構造方法     比如Person類, 編譯器新增一個無參構造 public Person(){} 05構造方法的呼叫賦值   A: 理解構造方法的格式和基本功能之後,現在就要研究構造方法是怎麼執行的呢?在建立物件的時候是如何初始化的呢?   構造方法是專門用來建立物件的,也就是在new物件時要呼叫構造方法。現在來看看如何呼叫構造方法。   B: 案例 class Person { // Person的成員屬性age和name private int age; private String name; // Person的構造方法,擁有引數列表 Person(int a, String nm) { // 接受到建立物件時傳遞進來的值,將值賦給成員屬性 age = a; name = nm; } public void speak() { System.out.println("name=" + name + ",age=" + age); } } class PersonDemo { public static void main(String[] args) { // 建立Person物件,並明確物件的年齡和姓名 Person p2 = new Person(23, "張三"); p2.speak(); } } 上述程式碼演示了建立物件時構造方法的呼叫。即在建立物件時,會呼叫與引數列表對應的構造方法 06構造方法的記憶體
  A:記憶體載入的過程   有一個Person類, 建立Person 物件new Person()   1、首先會將main方法壓入棧中,執行main方法中的 new Person(23,"張三");   2、在堆記憶體中分配一片區域,用來存放建立的Person物件,這片記憶體區域會有屬於自己的記憶體地址(0x88)。然後給成員變數進行預設初始化(name=null,age=0)。   3、執行構造方法中的程式碼(age = a ; name = nm;),將變數a對應的23賦值給age,將變數nm對應的”張三賦值給name,這段程式碼執行結束後,成員變數age和name的值已經改變。執行結束之後構造方法彈棧,Person物件建立完成。將Person物件的記憶體地址0x88賦值給p2。 07構造方法的過載   A:當在描述事物時,要不要在類中寫構造方法呢?這時要根據描述事物的特點來確定,當描述的事物在建立其物件時就要明確屬性的值,這時就需要在定義類的時候書寫帶引數的構造方法。   若建立物件時不需要明確具體的資料,這時可以不用書寫構造方法(不書寫也有預設的構造方法)。 構造方法的細節: 1、一個類中可以有多個構造方法,多個構造方法是以過載的形式存在的 2、構造方法是可以被private修飾的,作用:其他程式無法建立該類的物件。   B: 舉例 class Person { private int age; private String name; // 私有無引數的構造方法,即外界不能通過new Person();語句建立本類物件 private Person() { } // 多個構造方法是以過載的形式存在 Person(int a) { age = a; } Person(String nm, int a) { name = nm; age = a; } } 08構造方法和一般方法區別   A: 目前為止,學習兩種方法,分別為構造方法和一般方法,那麼他們之間有什麼異同呢?     1.格式不同 構造方法 : 修飾符 類名(引數型別 引數 ...){ 初始化成員變數 } 一般方法: 需要有返回值型別     2.作用不同 構造方法一般用來給成員變數初始化; 一般方法根據需求而定;     3.呼叫方式不同 構造方法建立物件時呼叫, 或者this() super() 語句呼叫 普通方法需要物件呼叫或者靜態方法直接呼叫靜態方法.     4.執行不同 構造方法在物件建立時就執行了,而且只執行一次。 一般方法是在物件建立後,需要使用時才被物件呼叫,並可以被多次呼叫。 09this在構造方法之間的呼叫   A: 在之前學習方法之間呼叫時,可以通過方法名進行呼叫。可是針對構造方法,無法通過構造方法名來相互呼叫。 構造方法之間的呼叫,可以通過this關鍵字來完成。 構造方法呼叫格式: this(引數列表);   B:呼叫構造方法的案例 class Person { // Person的成員屬性 private int age; private String name; // 無引數的構造方法 Person() { } // 給姓名初始化的構造方法 Person(String nm) { name = nm; } // 給姓名和年齡初始化的構造方法 Person(String nm, int a) { // 由於已經存在給姓名進行初始化的構造方法 name = nm;因此只需要呼叫即可 // 呼叫其他構造方法,需要通過this關鍵字來呼叫 this(nm); // 給年齡初始化 age = a; } } 10this在構造方法呼叫的記憶體圖   A: 被載入的程式碼 class Person { private int age; private String name; Person() { } Person(String nm) { name = nm; } Person(String nm, int a) { this(nm); age = a; } } class PersonDemo { public static void main(String[] args) { Person p = new Person("張三", 23); } }   B: 構造方法呼叫的原理圖   圖略 1、先執行main方法,main方法壓棧,執行其中的new Person(“張三”,23); 2、堆記憶體中開闢空間,併為其分配記憶體地址0x33,,緊接著成員變數預設初始化(name=null age = 0); 3、擁有兩個引數的構造方法(Person(String nm , int a))壓棧,在這個構造方法中有一個隱式的this,因為構造方法是給物件初始化的,那個物件呼叫到這個構造方法,this就指向堆中的那個物件。 4、由於Person(String nm , int a)構造方法中使用了this(nm);構造方法Person(String nm)就會壓棧,並將“張三”傳遞給nm。在Person(String nm , int a)構造方法中同樣也有隱式的this,this的值同樣也為0x33,這時會執行其中name = nm,即把“張三”賦值給成員的name。當賦值結束後Person(String nm , int a)構造方法彈棧。 5、程式繼續執行構造方法(Person(String nm , int a)中的age = a;這時會將23賦值給成員屬性age。賦值結束構造方法(Person(String nm , int a)彈棧。 6、當構造方法(Person(String nm , int a)彈棧結束後,Person物件在記憶體中建立完成,並將0x33賦值給main方法中的p引用變數。 注意: this到底代表什麼呢?this代表的是物件,具體代表哪個物件呢?哪個物件呼叫了this所在的方法,this就代表哪個物件。 呼叫其他構造方法的語句必須定義在構造方法的第一行,原因是初始化動作要最先執行。 11this簡易應用   A: 當在方法中出現了局部變數和成員變數同名的時候,那麼在方法中怎麼區別區域性變數成員變數呢?可以在成員變數名前面加上this.來區別成員變數和區域性變數   B: 舉例1 class Person { private int age; private String name; // 給姓名和年齡初始化的構造方法 Person(String name, int age) { // 當需要訪問成員變數是,只需要在成員變數前面加上this.即可 this.name = name; this.age = age; } public void speak() { System.out.println("name=" + this.name + ",age=" + this.age); } } class PersonDemo { public static void main(String[] args) { Person p = new Person("張三", 23); p.speak(); } }   C: 舉例2 學習完了構造方法、this的用法之後,現在做個小小的練習。 需求:在Person類中定義功能,判斷兩個人是否是同齡人 class Person { private int age; private String name; // 給姓名和年齡初始化的構造方法 Person(String name, int age) { // 當需要訪問成員變數是,只需要在成員變數前面加上this.即可 this.name = name; this.age = age; } public void speak() { System.out.println("name=" + this.name + ",age=" + this.age); } // 判斷是否為同齡人 public boolean equalsAge(Person p) { // 使用當前呼叫該equalsAge方法物件的age和傳遞進來p的age進行比較 // 由於無法確定具體是哪一個物件呼叫equalsAge方法,這裡就可以使用this來代替 /* * if(this.age == p.age) { return true; } return false; */ return this.age = p.age; } } 12super關鍵字_1   A: 子父類中構造方法的呼叫 在建立子類物件時,父類的構造方法會先執行,因為子類中所有構造方法的第一行有預設的隱式super();語句。   B: 格式: 呼叫本類中的構造方法 this(實參列表); 呼叫父類中的空引數構造方法 super(); 呼叫父類中的有引數構造方法 super(實參列表); 13super關鍵字_2   A:子類構造方法,有一個預設新增的構造方法 public class Student extends Person { public Student(){ super(); } }   B :為什麼子類物件建立都要訪問父類中的構造方法?因為子類繼承了父類的內容,所以建立物件時,必須要先看父類是如何對其內容進行初始化的,看如下程式 public class Test { public static void main(String[] args) { new Zi(); } } class Fu{ int num ; Fu(){ System.out.println("Fu構造方法"+num); num = 4; } } class Zi extends Fu{ Zi(){ //super(); 呼叫父類空引數構造方法 System.out.println("Zi構造方法"+num); } } 執行結果:    Fu構造方法0    Zi構造方法4 通過結果發現,子類構造方法執行時中,呼叫了父類構造方法,這說明,子類構造方法中有一句super()。 那麼,子類中的構造方法為什麼會有一句隱式的super()呢? 原因:子類會繼承父類中的內容,所以子類在初始化時,必須先到父類中去執行父類的初始化動作。這樣,才可以使用父類中的內容。 當父類中沒有空引數構造方法時,子類的構造方法必須有顯示的super語句,指定要訪問的父類有引數構造方法。


		



15super關鍵字_3
  A: 建立子類物件的時候會必須呼叫父類的構造方法。
	   子類預設會呼叫父類的無參構造, 但如果父類沒有無參構造,子類的構造方法繼續呼叫父類的無參構造就會報錯。
	   因此子類構造方法的第一行需要呼叫父類的構造方法,既可以呼叫父類的無參構造,也可以呼叫父類的有參構造,這樣語法上就不會報錯。
		


16super關鍵字_4
  A: 構造方法第一行,寫this()還是super()
  this() 是呼叫本類的構造方法,super()是呼叫父類的構造方法, 且兩條語句不能同時存在
  保證子類的所有構造方法呼叫到父類的構造方法即可
	
  B: 小結:
  無論如何,子類的所有構造方法,直接或間接必須呼叫到父類構造方法;
  子類的構造方法什麼都不寫,預設的構造方法第一行super()

		
17建立子類物件過程的細節
  A 建立子類物件過程的細節
	* 如果子類的構造方法第一行寫了this呼叫了本類其他構造方法,那麼super呼叫父類的語句還有嗎?
	* 這時是沒有的,因為this()或者super(),只能定義在構造方法的第一行,因為初始化動作要先執行。
	* 父類構造方法中是否有隱式的super呢?
	* 也是有的。記住:只要是構造方法預設第一行都是super();
	* 父類的父類是誰呢?super呼叫的到底是誰的構造方法呢?
	* Java體系在設計,定義了一個所有物件的父類Object

	* 注意:
		類中的構造方法預設第一行都有隱式的super()語句,在訪問父類中的空引數構造方法。所以父類的構造方法既可以給自己的物件初始化,也可以給自己的子類物件初始化。
		如果預設的隱式super()語句在父類中沒有對應的構造方法,那麼必須在構造方法中通過this或者super的形式明確要呼叫的構造方法。