Java正式上路之物件導向一

小小測試蝦皮糖發表於2020-12-31

1 物件導向

1.1萬物皆物件

我們是怎麼認識世界的?
人類從小就不斷的接觸到各種各類存在世界上的各種生物,然後通過事物的公共特性,將它們歸類,所以以後就不會出現見到貓叫老虎。那麼我們在現實生活中,是通過具體的某個事物歸納總結它們的公共特性然後產生類那麼類就描述了該種事物的的共別。性,相當於造事物的圖紙,我們可以根據這個圖紙去做出具體的實體物件。

物件:在現實生活中存在具體的一個事物。
:實際就是對某種型別事物的共性屬性與行為的抽取。
人類認識世界: 物件----類。
在java中: 類 -----物件。

使用計算機語言就是不斷的在描述現實生活中的事物。
java中描述事物通過類的形式體現,類是具體事物的抽象,概念上的定義。
物件即是該類事物實實在在存在的個體
類與物件的關係如圖
在這裡插入圖片描述
可以理解為:
類就是圖紙
汽車就是堆記憶體中的物件

1.2 物件導向的概述

“物件導向”(英語:Object Oriented,簡稱OO)是一種以事物為中心的程式設計思想。
物件導向程式設計(英語:Object-oriented programming,縮寫:OOP),是一種程式開發的方法。它將物件作為程式的基本單元,將程式和資料封裝其中,以提高軟體的重用性、靈活性和擴充套件性。
物件導向時相對於程式導向而言的(c則是一個典型的程式導向的語言),站在物件導向的角度去看問題,你則是物件的動作的指揮者。如果站在程式導向的角度去看問題,你則是動作的執行者。

1.3 物件導向與程式導向對比

“萬物皆物件”。

	1:買電腦
		1:程式導向
			1:查資料
			2:電腦城砍價
			3:被黑
			4:痛苦歸來
		1:物件導向
			1:找物件。老師
			2:老師.砍價
			3:老師.檢測電腦
			4:電腦成功購買
	2:吃飯
		1:程式導向
			1:自己動手做
			2:買菜
			3:洗菜
			4:煮飯炒菜
			5:很難吃,浪費時間
		2:物件導向
			1:找專業物件
			2:餐館.點餐
			3:餐館,做飯
			4:飯好吃,節約時間,精力
	3:找物件
		1:求介紹,相親,找現成的物件。(物件導向的思想先找有的物件,直                        					接拿來使用)
		2:不滿意,沒有物件,自己造一個。(sun沒有提供,自己造物件)

再例如:人開門,人開電視,人畫園。

1.4 程式導向

強調的是功能行為,程式導向是一種以過程為中心的程式設計思想。“程式導向”他們不支援豐富的“物件導向”特性(比如繼承、多型),就是分析出解決問題所需要的步驟,然後用函式把這些步驟一步一步實現,使用的時候一個一個依次呼叫就可以了。程式導向在這一系列工作的執行中,強調的是工作的執行。

1.5 物件

物件(object)代表現實世界中可以明確標識的一個實體。例如:一個學生、一張桌子、一間教室,一臺電腦都可以看做是一個物件。每個物件都有自己獨特的狀態標識和行為
物件的屬性(attribute,或者狀態(state)),學生有姓名和學號,該學生特有的姓名和學號就是該學生(物件)的屬性。
jenkins(behavior),是由方法定義,呼叫物件的一個方法,其實就是給物件發訊息,要求物件完成一個動作。可以定義學生物件具備學習的行為。學生物件可以呼叫學習的方法,執行學習的動作

1.6 物件導向的特徵

封裝(encapsulation)
繼承(inheritance)
多型(polymorphism)

開發的過程其實就是不斷的建立物件,使用物件,指揮物件做事情
設計的過程其實就是在管理和維護物件之間的關係

1.7 使用java來描述事物

案例:通過Java語言定義一個汽車類,並生產出汽車,有顏色,輪胎個數, 有執行的功能。
分析:
如何描述現實世界中的事物,描述該事物的屬性和行為,汽車具有顏色和輪胎數的屬性,具備執行的行為。
如何使用Java語言進行轉換?
根據對應關係:

屬性:類中的成員變數
行為:類中的成員函式

那麼定義Java類就是定義一個類的成員。汽車類具備的成員是:顏色,輪胎數,執行方法。

Car類定義流程:

  1. 使用class 關鍵字 定義類,
    class空格 類名。類名就是識別符號,命名規則,單詞的首字母大寫,多個單詞的首字母大寫。注意:不是規定,但是最好遵守
  2. 類名後緊跟一對{}表示類的開始和結束。
    有輪胎數屬性 int num; 不需要給num初始化值,因為汽車輪胎數不確定,有4,有6,有8。
    有顏色屬性 String color; 為什麼使用String 例如定義顏色"紅色"是字串型別。也不需要初始化值。
  3. 跑的行為(方法、函式) void run(){}
    方法中執行輸出語句。syso("跑啦。。。。");
public class Car {	
	String color;// 成員變數
	int num; // 成員變數

	// 成員函式
	public void run() {
		System.out.println(color + "的車,輪胎數:" + num + "個,跑起來了");
	}
}

1.8 物件的建立

建立Car物件

  1. 使用new關鍵詞,就像new陣列一樣
  2. 需要給型的汽車起一個名字,car
  3. 變數都是有型別的,car屬於什麼型別,屬於Car型別,叫做類型別
  4. Car car=new Car();
    圖紙畫好了,類定義成功了。如何根據圖紙生產汽車,在Java中如何根據類來生產一個物件。
    Java中生產汽車比較簡單,通過一個關鍵字”new”, 通過 new Car(); 就在記憶體中產生了一個實體,汽車物件就生產出來了。
    汽車物件生產出來後,還沒有名字,為了方便使用,需要起一個名字。就用小寫的C 來表示新車的名字。
    Java中的變數都需要有型別。那麼c 是什麼型別呢?c 是Car型別,所以c也叫做類型別變數。
class CarDemo {
	public static void main(String[] args) {
		// java 中建立物件,使用new關鍵字。在堆記憶體中開闢了空間。產生了一個實體。
		Car c = new Car();
		//為了方便使用生產的汽車,就起了一個名字。
		//那麼c是什麼型別,是Car型別。叫做類型別變數。
		//注意 c是持有的引用,新生產的汽車並沒有直接賦值給c,持有的只是一個引用。c就想電視遙控器一樣。
		c.run();  //使用物件的功能。
	}
}

1.9 物件成員的呼叫

有了car物件,呼叫物件成員

  1. 成員變數
  2. 成員方法
public class CarDemo {
	public static void main(String[] args) {
		Car c = new Car();
		//物件名.成員變數名將返回成員變數中儲存的數值
		int num=c.num; 
		System.out.println(num);
		
		//物件名.成員變數名,也可以給成員變數賦值
		c.num = 4;
		c.color = "black";
		
		//物件名.成員方法();
		c.run();
	}
}

2 區域性變數和成員變數

成員變數:  定義在類中變數
區域性變數:  定義在方法中變數

成員變數與區域性變數的區別:

  1. 應用範圍
    成員變數在整個類內都有效
    區域性變數只在其宣告的方法內有效
  2. 生命週期
    成員變數: 它屬於物件,它隨著物件的建立而建立,隨著物件的消失而消失
    區域性變數: 使用完馬上釋放空間
void show(int id){	
	for(int i=0;i<10;i++){
	 	for(int j=0;j<10;j++){
			System.out.println(id);
		}
	}
}
/**
這時候  id,i,j者是在方法內宣告的,全是區域性變數
j當裡層for迴圈執行它的生命週期開始,當裡層for結束,j消失
i當外層for迴圈執行它的生命週期開始,當外層for結束,j消失
id在方法被呼叫時開始,方法結束時,id消失.
*/
  1. 儲存位置
    成員變數屬於物件,它儲存在堆內,堆內的實體,當沒有引用指向其時,才垃圾回收清理。區域性變數存在棧記憶體中,當不在使用時,馬上就會被釋放。
  2. 初始值
    成員變數它儲存在堆中,如果沒有賦初值,它有預設值
    1.整數byte、short、int、long =0;
    2.char=’\uoooo’;
    3.boolean =flase;
    4.String =null;
    5.類型別 =null;
    6.陣列 =null;
    區域性變數,如果要想使用必須手動初始化
    1.方法中,引數列表中,語句中。
    2.必須給初始化值,沒有初始值,不能使用
    3.在棧記憶體中

3 物件的記憶體分析

案例一分析:

//汽車
class Car {
	//汽車應該具備的屬性
	int num;
	//汽車具備的顏色
	String color;
	//汽車跑的行為
	public void run(){
		System.out.println(num+"輪子的汽車跑起來啦");
	}
}
public class CarDemo{
	public static void main(String[] args){	
		//建立實體,並且給該實體起一個名字
		Car c = new Car();
		c.color = "red";
		c.num = 4;
		c.run();//指揮車進行執行。呼叫格式:物件.物件成員
		
	}
}

案例一記憶體分析
案例二分析:

public static void main(String[] args){	
	//建立實體,並且給該實體起一個名字
	Car c = new Car();
	Car c1 = new Car();
	c.color = "red";
	c1.num = 4;
	System.out.println(c1.color);
	c.run();//指揮車進行執行。呼叫格式:物件.物件成員
}

記憶體圖:
案例二記憶體分析
案例三

public static void main(String[] args){	
	//建立實體,並且給該實體起一個名字
	Car c = new Car();
	Car c1 = c;
	c.color = "red";
	c1.num = 4;
	c1.color = "green";
	System.out.println(c1.color);
	c.run();//指揮車進行執行。呼叫格式:物件.物件成員
}

記憶體圖三
案例三記憶體分析

4 物件導向練習

1:完成修理汽車的功能
2:分析
	1:物件導向的思想思考需要什麼物件
		1:汽車
			1:汽車有輪子
			2:有顏色
			3:有名字
			4:有執行的方法
		2:汽車修理廠
			1:有名字
			2:有地址
			3:有修理汽車的方法
3:程式碼實現
	1:定義汽車類
	2:定義汽車修理廠類
4:測試程式碼
	1:建立汽車物件
	2:汽車少了輪子無法執行。
	3:建立汽車修理廠
		1:設定廠名
		2:設定地址
	3:將汽車拖進修理廠
		1:執行汽車修理廠的修車方法,修理汽車
	4:取車
		1:開走汽車
package oop01;

/*
 物件導向之練習
 完成修理汽車的功能
 
 汽車類
 汽車修理廠類
 名字,地址, 修理汽車的功能
 */
public class Demo1 {
	public static void main(String[] args) {
		SCar sc = new SCar();
		sc.run();
        //將汽車輪子改為3個
		sc.num = 3;
		sc.run();

		CarFactory cf = new CarFactory();
		cf.name = "捷運達汽車修理站";
		cf.addr = "上海市浦東新區張東路1501號玉田花園旁";

		cf.repairCar(sc);
		sc.run();

		System.out.println();
	}
}

class SCar {
	String name = "smart";
	String color = "red";
	int num = 4;

	void run() {
		if (num < 4) {
			System.out.println("汽車壞了,趕緊修理吧。。。。");
		} else {
			System.out.println(name + ":" + color + ":" + num + ":跑起來了。。。。");
		}

	}

}

class CarFactory {
	String name;
	String addr;

	void repairCar(SCar sc) {
		sc.num = 4;
		System.out.println("汽車修好了。。。。");
	}
}

5 匿名物件

5.1匿名物件

沒有名字的實體,也就是該實體沒有對應的變數名引用。

5.2 匿名物件的用途

  1. 當物件對方法進行一次呼叫的時候,可以使用匿名物件對程式碼進行簡化。
    為什麼只對方法,而不呼叫屬性呢?因為匿名物件呼叫屬性沒意義。
    如果物件要多成員進行多次呼叫,必須給物件起個名字。
  2. 匿名物件可以實際引數進行傳遞。
    2:匿名物件的簡單演示
    1:new Car().run();
  3. 記憶體結構圖
    1:new Car().num=5;
    2:new Car().clor=“blue”;
    兩個new 是兩個不同的物件,在堆記憶體中有不同的空間,相互不相互干擾。
  4. 匿名物件的使用
    當只使用一次時可以使用匿名物件。執行完畢到;後該物件就變成了垃圾。
    new Car().run();
    執行方法時,可以將匿名物件作為實際引數,傳遞進去。

練習一
將小汽車改裝成3個輪子的黑車。
1:汽車類。
2:汽車修理廠

/*
 匿名物件
 匿名信
 修黑車
 汽車類
 黑車廠類
 把汽車的改成黑色3輪車。
 */
class Car {
	String name = "smart";
	String color = "red";
	int num = 4;
	void run() {
		System.out.println(name + ":" + color + ":" + num + ":跑起來了。。。。");
	}
}

class BlackCarFactory {
	String name;
	String addr;
	Car repairCar(Car c) {
		c.num = 3;
		c.color = "黑色";
		System.out.println("改裝成功啦。。。");	
	}
}

class Demo1 {
	public static void main(String[] args) {
		BlackCarFactory bcf = new BlackCarFactory();
		bcf.name = "捷運達汽車修理站";
		bcf.addr = "上海市浦東新區張東路1501號玉田花園旁";

		// 非匿名物件
		Car c = new Car();
		c.run();
		// 改裝
		bcf.repairCar(c);
		// 取車
		c.run();

		// 匿名物件一,只使用一次:
		// 如下建立了2個物件
		/*
		 * new Car().run();
		 * 
		 * new Car().run();
		 */

		// 匿名物件二,作為實際引數傳遞
		Car c2 = bcf.repairCar(new Car());
		c2.run();
		System.out.println();
	}
}

匿名物件使用總結
1. 匿名物件設定的屬性永遠無法獲取? 沒有引用變數指向那個物件。
2. 任何兩個匿名物件使用==比較,永遠返回false。
3. 匿名物件主要應用於實參。

6 封裝

我們日常使用的電腦主機,把cpu、記憶體、主機板等等都封裝到機箱裡面去。假如沒有機箱的話的出現什麼問題,主機、主機板全部都散落在一處,然後開機沒有開機按鈕,那麼需要我們直接操作接跳線才能把電腦開啟。這樣子的話假如操作不慎的話,會讓機器損壞危險,那麼假如用機箱封裝起來的話,那麼就不需要這樣子做了。體現了封裝的—安全特性
你拿電腦去加記憶體,可以直接給電腦給維修的人,等他加好記憶體了之後。你拿到的還是那個機箱,裡面發生了怎樣子的變化你並不知道。封裝的第二個好處-將變化隔離

在機箱裡面提供一個開機按鈕,而不需要你直接使用跳線開機的話,體現了封裝的—便於使用的特性。

只要機箱提供了一個開機的功能,然後無論這個機箱拿到哪裡去,都可以使用這個開機的功能.體現了封裝的—提供重複性的特性。

6.1 如果沒有封裝

模擬問題

  1. 描述Employee類。定義姓名,工號,性別的成員變數,和工作的方法。成員使用public修飾。
  2. 建立Employee物件,物件.成員的方式進行賦值。最後該物件呼叫工作方法。
  3. 總結:如果不使用封裝,很容易賦值錯誤,並且任何人都可以更改,造成資訊的 不安全。
  4. 問題解決:使用封裝
package oop01;

public class EmployeeDemo {
	public static void main(String[] args) {
		// 建立物件
		Employee jack = new Employee();

		// 進位制通過類名.成員的形式呼叫成員。初始化例項變數
		jack.name = "jack";
		jack.id = "123456";
		jack.gender = "男";

		// 呼叫成員方法
		jack.work();
		System.out.println();

		// 傳入非法的引數
		jack.gender = "不是男人";
		jack.work();

	}
}

class Employee {
	String name;
	String id;
	String gender;

	public void work() {
		System.out.println(id + ":" + name + ":" + gender + " 努力工作中!!!");
	}
}

6.2 封裝的實現

  1. 設定類的屬性為private(關鍵字),不能使用物件名.屬性名的方式直接訪問物件的屬性。
package oop01;

public class EmployeeDemo {
	public static void main(String[] args) {
		// 建立物件
		Employee jack = new Employee();

		//編譯報錯
		jack.name = "jack";
		jack.id = "123456";
		jack.gender = "男";

		

		// 編譯報錯
		jack.gender = "不是男人";
		jack.work();

	}
}

class Employee {
   //使用了private修飾了成員變數
	private String name;
	private String id;
	private String gender;

	public void work() {
		System.out.println(id + ":" + name + ":" + gender + " 努力工作中!!!");
	}
}

問題:
a. 為什麼之前可以通過物件名.屬性名的方式訪問?
b. public 成員修飾符,公共的誰都可以訪問。
c. private 成員修飾符,私有的,只有自己可以訪問。

  1. 修改Employee類 性別的修飾符修改為private
    編譯不通過
    private修飾的成員在自己所在的類中可以使用,在類外邊不可以使用。

  2. Employee類的gender的修飾符修改為private後,無法再類外呼叫,那麼如何給gender設定值?
    a. 對外提供公開的用於設定物件屬性的public方法

     	設定set
     	獲取get
    

    b. 在set方法中加入邏輯判斷,過濾掉非法資料。
    c. 將所有的成員變數封裝加上private,提供get、set方法

package oop01;
public class EmployeeDemo {
	public static void main(String[] args) {
		// 建立物件
		Employee jack = new Employee();

		// 呼叫公有方法,給成員變數賦值。
		jack.setId("007");
		jack.setName("jack");
		jack.setGender("男xx");

		// 獲取例項變數的值
		System.out.println(jack.getGender());
		System.out.println(jack.getId());
		System.out.println(jack.getName());

		// 呼叫成員方法
		jack.work();
	}
}

class Employee {
	private String name;
	private String id;
	private String gender;

	// 提供公有的get set方法
	public String getName() {
		return name;
	}

	public void setName(String n) {
		name = n;
	}

	public String getId() {
		return id;
	}

	public void setId(String i) {
		id = i;
	}

	public String getGender() {
		return gender;
	}

	public void setGender(String gen) {
		if ("男".equals(gen) || "女".equals(gen)) {
			gender = gen;
		} else {
			System.out.println("請輸入\"男\"或者\"女\"");
		}
	}

	public void work() {
		System.out.println(id + ":" + name + ":" + gender + " 努力工作中!!!");
	}
}

6.3 封裝的好處

1:隱藏了類的具體實現
2:操作簡單
3:提高物件資料的安全性

6.4 封裝練習

練習:描述一個計算器類
// 0. 使用詞霸確定類名
class Calculator{
	// 1. 檢視具體的計算器物件抽取所有計算器具有的共同屬性
	public String name = "我的計算器我做主";
    public double num1;
	public double num2;
	public char option;
	// 2. 檢視具體的計算器物件抽取所有計算器具有的共同功能
    // 2.1  定義接受資料的功能函式
	public void init( double a , char op , double b  ){
		num1 = a;
		option  = op;
		num2 = b;
	}
	// 2.2 定義計算的功能
	public void calculate(){
		switch ( option ){
		case '+': 
			System.out.println(  name + " : " + num1 + " + " + num2 + " = " + ( num1 + num2 ) );
			break;
		case '-': 
			System.out.println(  name + " : " + num1 + " - " + num2 + " = " + ( num1 - num2 ) );
            break;
		case '*': 
			System.out.println(  name + " : " + num1 + " * " + num2 + " = " + ( num1 * num2 ) );
            break;
		case '/':
			if( num2 != 0){
				System.out.println(  name + " : " + num1 + " / " + num2 + " = " + ( num1 / num2 ) );
			else
				System.out.println("除數不能為0!");
	            break;
	        }
		case '%':
			// 1.處理結果的符號問題,使得結果的符號滿足數學的要求
			// 2.解決NaN的問題
			System.out.println(  name + " : " + num1 + " % " + num2 + " = " + ( num1 % num2 ) );
            break;
		default : System.out.println("你在搗亂,我不理你,氣死你......");
	   }
	}
}

class Demo9 {
	public static void main(String[] args) {
        Calculator  cal = new Calculator();
		cal.init( 41 , '%' , 0 );
		cal.calculate();
		System.out.println("計算完畢!再來一次......");
	}
}

7 構造方法

我們人出生的時候,有些人一出生之後再起名字的,但是有些人一旦出生就已經起好名字的。那麼我們在java裡面怎麼在物件一旦建立就賦值呢?
在這裡插入圖片描述
在這裡插入圖片描述

7.1 構造方法的作用

構造方法作用:對物件進行初始化.
在這裡插入圖片描述

7.2 建構函式與普通的函式的區別

  1. 一般函式是用於定義物件應該具備的功能。而建構函式定義的是,物件在呼叫功能之前,在建立時,應該具備的一些內容。也就是物件的初始化內容。
  2. 建構函式是在物件建立時由jvm呼叫, 給物件初始化。一般函式是物件建立後,當物件呼叫該功能時才會執行。
  3. 普通函式可以使用物件多次呼叫,建構函式就在建立物件時呼叫。
  4. 建構函式的函式名要與類名一樣,而普通的函式只要符合識別符號的命名規則即可。
  5. 建構函式沒有返回值型別。

7.3 建構函式注意的細節

  1. 當類中沒有定義建構函式時,系統會指定給該類加上一個空引數的建構函式。這個是類中預設的建構函式。當類中如果自定義了建構函式,這時預設的建構函式就沒有了。
    備註:可以通過javap命令驗證。
  2. 在一個類中可以定義多個建構函式,以進行不同的初始化。多個建構函式存在於類中,是以過載的形式體現的。因為建構函式的名稱都相同。
class Perosn{
	private int id;
	
	private String name;
	
	private int age;
	
	public Perosn(){
		cry();
	}
	public Perosn(int id, String name, int age) {
		this.id = id;
		this.name = name;
		this.age = age;
	}
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	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 void cry(){
		System.out.println("哇哇哇....");
	}
}

問題:要求每個小孩出生都會哭,這份程式碼有兩個建構函式,如果需要每個小孩出生都要哭的話,那麼就需要在不同的建構函式中都呼叫cry()函式,但是這樣子的話造成了程式碼重複問題,那麼怎麼解決呢?構造程式碼塊。

7.4 構造程式碼塊

構造程式碼塊作用:給所有的物件進行統一的初始化。

class Perosn{
	private int id;
	
	private String name;
	
	private int age;
	
	{
		cry();// 每個Person物件建立出來都會執行這裡的程式碼
	}
	
	public Perosn(){
		cry();
	}
	public Perosn(int id, String name, int age) {
		this.id = id;
		this.name = name;
		this.age = age;
	}
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	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 void cry(){
		System.out.println("哇哇哇....");
	}
}

程式碼塊與建構函式區別

  1. 構造程式碼塊和建構函式的區別,構造程式碼塊是給所有物件進行統一初始化, 建構函式給對應的物件初始化。
  2. 構造程式碼塊的作用:它的作用就是將所有構造方法中公共的資訊進行抽取。
    例如孩子一出生統一哭
class Boy {
	String name;
	int age;
	String gender;
     // 構造程式碼塊,給所有物件進行初始化。
	{
		System.out.println("哭。。。");
	}    
	Boy() {
		System.out.println("無參構造");
	}
	Boy(String n, int a, String g) {
		name = n;
		age = a;
		gender = g;
		System.out.println("有參構造");
	}
	void run() {
		System.out.println("跑...");
	}
}

class Demo9 {
	public static void main(String[] args) {
		System.out.println();
		Boy b = new Boy();

		Boy b2 = new Boy("jack", 1, "男");

	}
}

8 this關鍵字

疑問:建立的p物件為什麼沒有值。

解答:name與age在指定的建構函式裡面已經存在,當name=name這個語句執行的時候,如果jvm在該方法內能尋找到該變數,則不會去尋找成員變數,那麼要想指定給成員變數或物件的屬性進行初始化賦值,那麼必須指定name是成員屬性。

8.1 this 的概述

this關鍵字代表是物件的引用。也就是this在指向一個物件,所指向的物件就是呼叫該函式的物件引用。

  1. 沒有this會出現什麼問題
/**
1:定義Person類
	1:有姓名年齡成員變數,有說話的方法。
	2:定義構造方法,無參的,多個有參的。都要實現。
*/
class Person {

	String name;
	int age;
	//無引數建構函式
	Person() {
		System.out.println("這是無參的建構函式");
	}
	
	//有引數建構函式
	Person(int a) {
		age = a;
		System.out.println("有參構造1");
	}
	//有引數建構函式
	Person(String n) {
		name = n;
		System.out.println("有參構造2");
	}
	//有引數建構函式
	Person(int a, String n) {
		age = a;
		name = n;
		System.out.println("有參構造");
	}
	
	//普通函式
	void speak() {
		System.out.println("hah");
	}
}
  1. 假設定義40個成員變數,第一個有參構造初始化20個變數,第二個有參構造需要初始化40個變數。
    1:第二個有參構造想要使用第一個有參構造。
    2:成員函式相互之間可以呼叫。建構函式可以嗎?
  2. 編譯失敗,那麼建構函式之間應該存在相互呼叫的模式。this就可以完成這個工作。
class Person {
	String name;
	int age;
	Person() {

	}
	Person(String n){
		name=n;
	}
	Person(String n, int a) {
        //編譯報錯
		Person(n);
		age = a;
	}
}

總結:實際工作中,存在著建構函式之間的相互呼叫,但是建構函式不是普通的成員函式,不能通過函式名自己接呼叫。所以sun公司提供this關鍵字。

8.2 this是什麼

  1. 在建構函式中列印this
  2. 建立物件,列印物件名p
  3. this和p是一樣的都是記憶體地址值。
  4. this代表所在函式所屬物件的引用。
class Student {
	String name;
	String gender;
	int age;

	Student() {
	}

	Student(String name) {
		this();
		this.name = name;
	}

	Student(String name, String gender, int age) {
		this(name);
		System.out.println(this); // Student@c17164
		this.gender = gender;
		this.age = age;
	}

	void speak() {
		run();
		System.out.println("姓名:" + name + " 性別:" + gender + " 年齡:" + age + " 哈哈!!!");
	}
	void run() {
		System.out.println("run.....");
	}
}

class Demo2 {
	public static void main(String[] args) {
		Student p = new Student("jack", "男", 20);
		System.out.println(p); // Student@c17164
		Student p2 = new Student("rose", "女", 18);
		System.out.println(p2);
		p.speak();
	}
}
  1. 建構函式的相互呼叫,在編譯時期會報錯
class Student {
	String name;
	String gender;
	int age;
    //建構函式見相互呼叫
	Student() {
		this(null);
	}
    //建構函式見相互呼叫
	Student(String name) {
		this();
		this.name = name;
	}

	Student(String name, String gender, int age) {
		this(name);
		this.gender = gender;
		this.age = age;
	}

	void speak() {
		run();
		System.out.println("姓名:" + name + " 性別:" + gender + " 年齡:" + age + " 哈哈!!!");
	}

	void run() {
		System.out.println("run.....");
	}

}
  1. this只能在非靜態中(沒有static修飾的)函式使用
  2. 建構函式間相互呼叫必須放在建構函式的第一個語句中,否則編譯錯誤
  3. 可以解決建構函式中物件屬性和函式形參的同名問題。

相關文章