今日內容介紹
一、構造方法
二、this關鍵字
三、super關鍵字
四、綜合案例java
在開發中常常須要在建立對象的同時明確對象的屬性值, 好比員工入職公司就要明確他的姓名、年齡等屬性信息。 那麼,建立對象就要明確屬性值,那怎麼解決呢?也就是在建立對象的時候就要作的事情, 當使用new關鍵字建立對象時,怎麼給對象的屬性初始化值呢? 這就要學習Java另一門小技術,構造方法。
從字面上理解即爲構建創造時用的方法,即就是對象建立時要執行的方法。既然是對 象建立時要執行的方法,那麼只要在new對象時, 知道其執行的構造方法是什麼,就能夠在執行這個方法的時候給對象進行屬性賦值。
在new的同時給成員變量賦值,給對象屬性進行初始化。
Perons p = new Person("張三",23); 在new 的時候給p對象的name屬性和age屬性進行賦值,使這個對象的屬性有值。
構造方法的格式: 修飾符 構造方法名(參數列表) { }
構造方法沒有返回值類型。也不須要寫返回值。由於它是爲構建對象的,對象建立完,方法就執行結束。 構造方法名稱必須和類型保持一致。 構造方法沒有具體的返回值。 構造方法的代碼體現:
class Person { // Person的成員屬性age和name private int age; private String name; // Person的構造方法,擁有參數列表 Person(int a, String nm) { // 接受到建立對象時傳遞進來的值,將值賦給成員屬性 age = a; name = nm; } }
在new 對象的時候自動調用執行。
構造方法是專門用來建立對象的,也就是在new對象時要調用構造方法。如今來看看如何調用構造方法。網絡
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(); } }
上述代碼演示了建立對象時構造方法的調用。即在建立對象時,會調用與參數列表對應的構造方法ide
A:內存加載的過程學習
有一個Person類, 建立Person 對象new Person() 一、首先會將main方法壓入棧中,執行main方法中的 new Person(23,"張三"); 二、在堆內存中分配一片區域,用來存放建立的Person對象,這片內存區域會有屬 於本身的內存地址(0x88)。而後給成員變量進行默認初始化(name=null,age=0)。 三、執行構造方法中的代碼(age = a ; name = nm;),將變量a對應的23賦值給age,將變 量nm對應的」張三賦值給name,這段代碼執行結束後,成員變量age和name的值已經改變。 執行結束以後構造方法彈棧,Person對象建立完成。將Person對象的內存地址0x88賦值給p2。
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.執行不一樣 構造方法在對象建立時就執行了,並且只執行一次。 通常方法是在對象建立後,須要使用時才被對象調用,並能夠被屢次調用。
A: 在以前學習方法之間調用時,能夠經過方法名進行調用。但是針對構造方法,沒法經過構造方法名來相互調用。
構造方法之間的調用,能夠經過this關鍵字來完成。
構造方法調用格式:
this(參數列表);網站
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; } }
A: 被加載的代碼
class Person {
private int age;
private String name;this
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); } }
一、先執行main方法,main方法壓棧,執行其中的new Person(「張三」,23);設計
二、堆內存中開闢空間,併爲其分配內存地址0x33,,緊接着成員變量默認初始化(name=null age = 0);code
三、擁有兩個參數的構造方法(Person(String nm , int a))壓棧,在這個構造方法中有一個隱式的this,由於構造方法是給對象初始化的,那個對象調用到這個構造方法,this就指向堆中的那個對象。對象
四、因爲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)構造方法彈棧。
五、程序繼續執行構造方法(Person(String nm , int a)中的age = a;這時會將23賦值給成員屬性age。賦值結束構造方法(Person(String nm , int a)彈棧。
六、當構造方法(Person(String nm , int a)彈棧結束後,Person對象在內存中建立完成,並將0x33賦值給main方法中的p引用變量。
注意:
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; } }
A: 子父類中構造方法的調用
在建立子類對象時,父類的構造方法會先執行,由於子類中全部構造方法的第一行有默認的隱式super();語句。
調用本類中的構造方法 this(實參列表); 調用父類中的空參數構造方法 super(); 調用父類中的有參數構造方法 super(實參列表);
public class Student extends Person { public Student(){ super(); } }
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語句,指定要訪問的父類有參數構造方法。
子類默認會調用父類的無參構造, 但若是父類沒有無參構造,子類的構造方法繼續調用父類的無參構造就會報錯。 所以子類構造方法的第一行須要調用父類的構造方法,既能夠調用父類的無參構造,也能夠調用父類的有參構造,這樣語法上就不會報錯。
* A: 構造方法第一行,寫this()仍是super() * this() 是調用本類的構造方法,super()是調用父類的構造方法, 且兩條語句不能同時存在 * 保證子類的全部構造方法調用到父類的構造方法便可 * B: 小結: * 不管如何,子類的全部構造方法,直接或間接必須調用到父類構造方法; * 子類的構造方法什麼都不寫,默認的構造方法第一行super()
* A 建立子類對象過程的細節 * 若是子類的構造方法第一行寫了this調用了本類其餘構造方法,那麼super調用父類的語句還有嗎? * 這時是沒有的,由於this()或者super(),只能定義在構造方法的第一行,由於初始化動做要先執行。 * 父類構造方法中是否有隱式的super呢? * 也是有的。記住:只要是構造方法默認第一行都是super(); * 父類的父類是誰呢?super調用的究竟是誰的構造方法呢? * Java體系在設計,定義了一個全部對象的父類Object * 注意: 類中的構造方法默認第一行都有隱式的super()語句,在訪問父類中的空參數構造方法。 因此父類的構造方法既能夠給本身的對象初始化,也能夠給本身的子類對象初始化。 若是默認的隱式super()語句在父類中沒有對應的構造方法,那麼必須在構造方法中經過\ this或者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(); } }
某IT公司有多名員工,按照員工負責的工做不一樣,進行了部門的劃分(研發部員工、維護部員工)。 研發部根據所需研發的內容不一樣,又分爲JavaEE工程師、Android工程師;維護部根據所需維護 的內容不一樣,又分爲網絡維護工程師、硬件維護工程師。 公司的每名員工都有他們本身的員工編號、姓名,並要作它們所負責的工做。 工做內容 JavaEE工程師:員工號爲xxx的 xxx員工,正在研發淘寶網站 Android工程師:員工號爲xxx的 xxx員工,正在研發淘寶手機客戶端軟件 網絡維護工程師:員工號爲xxx的 xxx員工,正在檢查網絡是否暢通 硬件維護工程師:員工號爲xxx的 xxx員工,正在修復打印機 請根據描述,完成員工體系中全部類的定義,並指定類之間的繼承關係。進行XX工程師類的對象建立,完成工做方法的調用。
根據上述部門的描述,得出以下的員工體系圖 根據員工信息的描述,肯定每一個員工都有員工編號、姓名、要進行工做。則, 把這些共同的屬性與功能抽取到父類中(員工類),關於工做的內容由具體的工程師來進行指定。 工做內容 JavaEE工程師:員工號爲xxx的 xxx員工,正在研發淘寶網站 Android工程師:員工號爲xxx的 xxx員工,正在研發淘寶手機客戶端軟件 網絡維護工程師:員工號爲xxx的 xxx員工,正在檢查網絡是否暢通 硬件維護工程師:員工號爲xxx的 xxx員工,正在修復打印機 建立JavaEE工程師對象,完成工做方法的調用
public abstract class Employee { private String id;// 員工編號 private String name; // 員工姓名 //空參數構造方法 public Employee() { super(); } //有參數構造方法 public Employee(String id, String name) { super(); this.id = id; this.name = name; } public String getId() { return id; } public void setId(String id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } //工做方法(抽象方法) public abstract void work(); }
public abstract class Developer extends Employee { //空參數構造方法 public Developer() { super(); } //有參數構造方法 public Developer(String id, String name) { super(id, name); } }
public abstract class Maintainer extends Employee { //空參數構造方法 public Maintainer() { super(); } //有參數構造方法 public Maintainer(String id, String name) { super(id, name); } }
public class JavaEE extends Developer { //空參數構造方法 public JavaEE() { super(); } //有參數構造方法 public JavaEE(String id, String name) { super(id, name); } @Override public void work() { System.out.println("員工號爲 " + getId() + " 的 " + getName() + " 員工,正在研發淘寶網站"); } }
public class Android extends Developer { //空參數構造方法 public Android() { super(); } //有參數構造方法 public Android(String id, String name) { super(id, name); } @Override public void work() { System.out.println("員工號爲 " + getId() + " 的 " + getName() + " 員工,正在研發淘寶手機客戶端軟件"); } }
public class Network extends Maintainer { //空參數構造方法 public Network() { super(); } //有參數構造方法 public Network(String id, String name) { super(id, name); } @Override public void work() { System.out.println("員工號爲 " + getId() + " 的 " + getName() + " 員工,正在檢查網絡是否暢通"); } }
public class Hardware extends Maintainer { //空參數構造方法 public Hardware() { super(); } //有參數構造方法 public Hardware(String id, String name) { super(id, name); } @Override public void work() { System.out.println("員工號爲 " + getId() + " 的 " + getName() + " 員工,正在修復打印機"); } }
public class Test { public static void main(String[] args) { //建立JavaEE工程師員工對象,該員工的編號000015,員工的姓名 小明 JavaEE ee = new JavaEE("000015", "小明"); //調用該員工的工做方法 ee.work(); } }
一、構造方法的格式是什麼?有哪些注意事項?
權限修飾符 類名(參數列表){方法體}
二、構造方法能夠重載嗎? 裏邊能夠有return語句嗎?
能夠重載 能夠有return但不能有返回值
三、給成員變量賦值有幾種方式?有什麼區別?
get/set
直接賦值
帶參構造器賦值
初始化
static 代碼塊賦值
默認構造器賦值
4.編寫一個完整的Person類,使用this關鍵字給成員變量進行賦值.
在測試類中測試
代碼:
public class HomeWork { public static void main(String[] args) { Person p = new Person(); p.run(); System.out.println(p.getAge()); System.out.println(p.getName()); } } class Person { private int age; private String name; public int getAge() { return age; } public String getName() { return name; } public void run() { this.age = 10; this.name = "邊天旭"; } }
五、根據需求,完成以下代碼(按照標準格式寫),並在測試類中進行測試。
標準格式包含: 私有屬性 無參構造 有參構造 setter 和getter 需求中的方法 需求一: 員工類Employee 屬性:姓名name,工號id,工資salary 行爲:顯示全部成員信息的方法show()
代碼:
class Employee { private String name; private String id; private double salary; public Employee() { super(); // TODO Auto-generated constructor stub } public Employee(String name, String id, double salary) { super(); this.name = name; this.id = id; this.salary = salary; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getId() { return id; } public void setId(String id) { this.id = id; } public double getSalary() { return salary; } public void setSalary(double salary) { this.salary = salary; } public void show() { System.out.println("姓名:" + this.name); System.out.println("工號:" + this.id); System.out.println("工資:" + this.salary); } }
需求二: 動物類Animal 屬性:姓名name,年齡age 行爲:吃飯eat,睡覺sleep
代碼:
class Animal { private String name; private int 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; } public Animal(String name, int age) { super(); this.name = name; this.age = age; } public Animal() { super(); } public void eat() { System.out.println("動物吃飯"); } public void sleep() { System.out.println("動物睡覺"); } } 需求三: 人類Person 屬性:姓名name,年齡age,性別gender 行爲:學習study,睡覺sleep
代碼:
class person { private String name; private int age; private char gender; public person() { super(); // TODO Auto-generated constructor stub } public person(String name, int age, char gender) { super(); this.name = name; this.age = age; this.gender = gender; } 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; } public char getGender() { return gender; } public void setGender(char gender) { this.gender = gender; } public void study() { System.out.println("學生學習"); } public void sleep() { System.out.println("學生睡覺"); } }