4、構造方法、this、super
構造方法
構造方法引入
* A:構造方法的引入 在開發中經常需要在創建對象的同時明確對象的屬性值,比如員工入職公司就要明確他的姓名、年齡等屬性信息。 那麽,創建對象就要明確屬性值,那怎麽解決呢?也就是在創建對象的時候就要做的事情,當使用new關鍵字創建對象時,怎麽給對象的屬性初始化值呢? 這就要學習Java另外一門小技術,構造方法。 * B: 那什麽是構造方法呢? 從字面上理解即為構建創造時用的方法,即就是對象創建時要執行的方法。既然是對象創建時要執行的方法,那麽只要在new對象時, 知道其執行的構造方法是什麽,就可以在執行這個方法的時候給對象進行屬性賦值。
構造方法作用
* A: 構造方法的作用:
在new的同時給成員變量賦值,給對象屬性進行初始化。
* B: 舉例:
Perons p = new Person("張三",23);
在new 的時候給p對象的name屬性和age屬性進行賦值,使這個對象的屬性有值。
?
構造方法的定義和運行特點
* 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 對象的時候自動調用執行。
默認添加的構造方法
* A: 每一class類都必須有一個構造方法,構造方法不寫也有。
編譯的時候,javac,系統會自動檢查類中是否有構造方法,如果沒有編譯器就會自動添加一個構造方法
比如Person類, 編譯器添加一個無參構造 public Person(){}
構造方法的調用賦值
* 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(); } } 上述代碼演示了創建對象時構造方法的調用。即在創建對象時,會調用與參數列表對應的構造方法
構造方法的內存
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。
構造方法的重載
* 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;
}
}
?
構造方法和一般方法區別
* A: 目前為止,學習兩種方法,分別為構造方法和一般方法,那麽他們之間有什麽異同呢?
1.格式不同
構造方法 : 修飾符 類名(參數類型 參數 ...){
初始化成員變量
}
一般方法: 需要有返回值類型
2.作用不同
構造方法一般用來給成員變量初始化;
一般方法根據需求而定;
3.調用方式不同
構造方法創建對象時調用, 或者this() super() 語句調用
普通方法需要對象調用或者靜態方法直接調用靜態方法.
4.執行不同
構造方法在對象創建時就執行了,而且只執行一次。
一般方法是在對象創建後,需要使用時才被對象調用,並可以被多次調用。
?
this關鍵字
this在構造方法之間的調用
* 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;
}
}
this在構造方法調用的內存圖
* 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就代表哪個對象。
? 調用其他構造方法的語句必須定義在構造方法的第一行,原因是初始化動作要最先執行。
this簡易應用
* 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;
}
}
super關鍵字
super關鍵字_1
* A: 子父類中構造方法的調用
在創建子類對象時,父類的構造方法會先執行,因為子類中所有構造方法的第一行有默認的隱式super();語句。
* B: 格式:
調用本類中的構造方法
this(實參列表);
調用父類中的空參數構造方法
super();
調用父類中的有參數構造方法
super(實參列表);
super關鍵字_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語句,指定要訪問的父類有參數構造方法。
子類父類的內存圖
super關鍵字_3
* A: 創建子類對象的時候會必須調用父類的構造方法。
子類默認會調用父類的無參構造, 但如果父類沒有無參構造,子類的構造方法繼續調用父類的無參構造就會報錯。
因此子類構造方法的第一行需要調用父類的構造方法,既可以調用父類的無參構造,也可以調用父類的有參構造,這樣語法上就不會報錯。
super關鍵字_4
* A: 構造方法第一行,寫this()還是super()
* this() 是調用本類的構造方法,super()是調用父類的構造方法, 且兩條語句不能同時存在
* 保證子類的所有構造方法調用到父類的構造方法即可
* B: 小結:
* 無論如何,子類的所有構造方法,直接或間接必須調用到父類構造方法;
* 子類的構造方法什麽都不寫,默認的構造方法第一行super()
?
創建子類對象過程的細節
* A 創建子類對象過程的細節
* 如果子類的構造方法第一行寫了this調用了本類其他構造方法,那麽super調用父類的語句還有嗎?
* 這時是沒有的,因為this()或者super(),只能定義在構造方法的第一行,因為初始化動作要先執行。
* 父類構造方法中是否有隱式的super呢?
* 也是有的。記住:只要是構造方法默認第一行都是super();
* 父類的父類是誰呢?super調用的到底是誰的構造方法呢?
* Java體系在設計,定義了一個所有對象的父類Object
* 註意:
類中的構造方法默認第一行都有隱式的super()語句,在訪問父類中的空參數構造方法。所以父類的構造方法既可以給自己的對象初始化,也可以給自己的子類對象初始化。
如果默認的隱式super()語句在父類中沒有對應的構造方法,那麽必須在構造方法中通過this或者super的形式明確要調用的構造方法。
super的應用
* A: 練習:描述學生和工人這兩個類,將他們的共性name和age抽取出來存放在父類中,並提供相應的get和set方法,同時需要在創建學生和工人對象就必須明確姓名和年齡
* 案例:
//定義Person類,將Student和Worker共性抽取出來
class Person {
private String name;
private int age;
public Person(String name, int age) {
// super();
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
class Student extends Person {
// Student類的構造方法
Student(String name, int age) {
// 使用super關鍵字調用父類構造方法,進行相應的初始化動作
super(name, age);
}
public void study() {// Studnet中特有的方法
System.out.println(this.getName() + "同學在學習");
}
}
class Worker extends Person {
Worker(String name, int age) {
// 使用super關鍵字調用父類構造方法,進行相應的初始化動作
super(name, age);
}
public void work() {// Worker 中特有的方法
System.out.println(this.getName() + "工人在工作");
}
}
public class Test {
public static void main(String[] args) {
Student stu = new Student("小明",23);
stu.study();
Worker w = new Worker("小李",45);
w.work();
}
}
總結
this關鍵字
:
? this關鍵字,本類對象的引用
? this是在方法中使用的,哪個對象調用了該方法,那麽,this就代表調用該方法的對象引用
? this什麽時候存在的?當創建對象的時候,this存在的
? this的作用:用來區別同名的成員變量與局部變量(this.成員變量)
? public void setName(String name) {
? this.name = name;
? }
? 構造方法: 用來給類的成員進行初始化操作
? 格式:
? 修飾符 類名 (參數列表) { }
構造方法的特點
:
? 1)方法名與類名相同
? 2)沒有返回值,也沒有返回值類型,連void也沒有
? 構造方法什麽時候會被調用執行?
? 只有在創建對象的時候才可以被調用
super關鍵字
:
? super: 指的是父類的存儲空間(理解為父類的引用)
? 調用父類的成員變量:
? super.成員變量;
? 調用父類的構造方法:
? super(參數);
? 調用方法的成員方法:
? super.成員方法();
繼承中的構造方法註意事項
:
? 1)如果我們手動給出了構造方法,編譯器不會在給我們提供默認的空參數構造方法
? 如果我們沒寫任何的構造方法,編譯器提供給我們一個空參數構造方法
? 2)在構造方法中,默認的第一條語句為 super();
? 它是用來訪問父類中的空參數構造方法,進行父類成員的初始化操作
? 3)當父類中沒有空參數構造方法的時候,怎麽辦?
? a: 通過 super(參數) 訪問父類有參數的構造方法
? b: 通過 this(參數) 訪問本類中其他構造方法
? 註意:[本類中的其他構造方法已經能夠正常訪問父類構造方法]
? 4)super(參數) 與 this(參數) 不能同時在構造方法中存在
4、構造方法、this、super