引用數據類型 類 封裝 類與對象 面向對象 私有private this關鍵字

1. 引用數據類型分類

    

提到引用數據類型(類),其實我們對它並不陌生,如使用過的Scanner類、Random類。

我們可以把類的類型爲兩種: 

  第一種,Java爲我們提供好的類,如Scanner類,Random類等,這些已存在的類中包含了很多的方法與屬性,可供我們使  用。

  第二種,我們自己創建的類,按照類的定義標準,可以在類中包含多個方法與屬性,來供我們使用。

這裏我們主要介紹第二種情況的簡單使用。

 1. 自定義數據類型概述  

 我們在Java中,將現實生活中的事物抽象成了代碼。這時,我們可以使用自定義的數據類型()來描述(映射)現實生活中的事物。

類,它是引用數據類型,與之前學習的所有引用數據類型相同,自定義類也是一種數據類型。只是自定義類型並非Java爲我們預先提供好的類型,而是我們自己定義的一種引用數據類型用來描述一個事物。 

2. 類的定義與使用 

java代碼映射成現實事物的過程就是定義類的過程。

我們就拿一部手機進行分析,它能用來做什麼呢?它可以打電話,上網,聊微信等,這些就是手機所提供的功能,也就是方法;手機也有它的特徵,如顏色、尺寸大小、品牌型號等,這些就是手機的特徵,也就是屬性。

目前,我們只關注類中的屬性,類中的方法在文章下面面向對象部分再進行介紹。

1.3.1類的定義格式
類的定義格式
創建java文件,與類名相同
public class 類名{
	數據類型  屬性名稱1;
	數據類型  屬性名稱2;
	…
}

通過類的定義格式,來進行手機類的描述,如下所示
public class Phone {
	/*
	 * 屬性
	 */
	String brand;// 品牌型號
	String color;// 顏色
	double size; // 尺寸大小
}

上述代碼,就是創建一個類的的過程,類的名稱我們給起名爲Phone,類中包含了三個屬性(brand品牌型號、color顏色、size尺寸大小)。注意,類中定義的屬性沒有個數要求。

1.類的使用格式

Phone類定義好後,我們就可以使用這個類了,使用方式和使用引用數據類型Scanner類相似。格式如下:

導包:我們將所有的類放到同一個文件夾下,可以避免導包。

創建對象:數據類型  變量名 = new 數據類型();

調用方法:目前我們定義的自定義類不涉及方法,只是屬性(自定義類中的方法部分在面向對象部分講解)

訪問屬性:變量名.屬性 (這是當前的方式,後期會採取調用方法的方式替代掉直接訪問的方式來完成對屬性的訪問。)

當有了Phone數據類型的變量後,我們就可以使用Phone類中的屬性了。對屬性的訪問我們來演示一下,如下所示:
public class Test {
	public static void main(String[] args) {
		//定義了一個Phone類型的變量p
		Phone p = new Phone();
		/*
		 * 通過p,使用Phone中的屬性
		 */
		//訪問p中的brand品牌屬性
    p.brand = "蘋果6s";[爲p中brand屬性賦值爲”蘋果6s”]
   //訪問p中的color顏色屬性
		p.color = "白色";[爲p中color屬性賦值爲”白色”]
   //訪問p中的size尺寸大小屬性
   p.size = 5.5;[爲p中size屬性賦值爲5.5]

System.out.println("手機品牌爲" + p.brand[使用p中brand屬性值參與運算]);
System.out.println("手機顏色爲" + p.color[使用p中color屬性值參與運算]);
System.out.println("手機尺寸大小爲" + p.size[使用p中size屬性值參與運算]);

 自定義類型注意事項與內存圖

上述代碼中,通過類Phone創建出來的變量p,它相當於我們生活中的盒子,裏面包含了它能夠使用的屬性。

通過 p.屬性名 就可以對屬性進行操作

l 與引用類型數組類似,引用類型的自定義類型的變量,直接變量時,結果爲對象地址值,這裏可以通過內存圖簡單解釋。



理解什麼是面向過程、面向對象

面向過程與面向對象都是我們編程中,編寫程序的一種思維方式。

面向過程的程序設計方式,是遇到一件事時,思考“我該怎麼做”,然後一步步實現的過程。

例如:公司打掃衛生(擦玻璃、掃地、拖地、倒垃圾等),按照面向過程的程序設計方式會思考“打掃衛生我該怎麼做,然後一件件的完成”,最後把公司衛生打掃乾淨了。

面向對象的程序設計方式,是遇到一件事時,思考“我該讓誰來做”,然後那個“誰”就是對象,他要怎麼做這件事是他自己的事,反正最後一羣對象合力能把事就好就行了。

例如,公司打掃衛生(擦玻璃、掃地、拖地、倒垃圾等),按照面向對象的程序設計方式會思考“我該讓誰來做,如小明擦玻璃、讓小麗掃地、讓小郭拖地、讓小強倒垃圾等”,這裏的“小明、小麗、小郭、小強”就是對象,他們要打掃衛生,怎麼打掃是他們自己的事,反正最後一羣對象合力把公司衛生打掃乾淨了。

 面向對象舉例

l 買電腦(組裝機)

先使用面向過程說明買電腦這件事:假如我們需要買組裝電腦,這時首先會在網上查詢具體每一個硬件的參數和報價。然後會去電腦城進行多家詢價,接着詢價結束後回家根據具體的結果分析出自己比較滿意的哪家報價,接着會到這家店裏進行組裝,組裝時還需要進行現場監督,組裝完成安裝相應的系統,然後電腦抱回家。

分析上述整個過程大體分一下幾步:上網查詢參數和報價、電腦城詢價、現場安裝和監督、抱電腦回家。在整個過程中我們參與了每一個細節,並且會感覺相當累。

使用面向對象說明買電腦這件事:假如我們需要買組裝機,這時應該找一個懂電腦硬件的人,讓他幫我們查看參數和報價,並進行詢價和殺價,以及現場組裝監督。而我們自己並不需要親歷親爲具體怎麼做,只要告訴這個人我們想要的具體需求即可。

分析上述整個過程,發現瞬間變的十分輕鬆,只要找到懂電腦硬件的這個人,我們的問題都可以解決。並且在這個過程中我們不用那麼辛苦。

 面向對象思維方式的好處

通過生活中的真實場景使用面向對象分析完之後,我們開始分析面向過程和麪向對象的差異做出總結:

l 面向對象思維方式是一種更符合人們思考習慣的思想

l 面向過程思維方式中更多的體現的是執行者(自己做事情),面向對象中更多的體現是指揮者(指揮對象做事情)。

l 面向對象思維方式將複雜的問題簡單化。


類與對象

 對象在需求中的使用

對面向對象有了瞭解之後,我們來說說在具體問題中如何使用面向對象去分析問題,和如何使用面向對象。

我們把大象裝冰箱爲例進行分析。

在針對具體的需求,可以使用名詞提煉的辦法進行分析,尋找具體的對象。

需求:把大象裝冰箱裏

對象:大象、冰箱

分三步:

1、打開冰箱門

2、將大象裝進去

3、關閉冰箱門

分析發現打開、裝、關閉都是冰箱的功能。即冰箱對象具備如下功能:

冰箱打開

冰箱存儲

冰箱關閉

用僞代碼描述,上述需求中有兩個具體的事物 大象  冰箱

描述大象:

class 大象

{

}

描述冰箱

class冰箱

{

void 打開(){}

void 存儲(大象){}

void 關閉(){}

}

當把具體的事物描述清楚之後,需要使用這些具體的事物,Java使用具體的事物,需要通過new關鍵字來創建這個事物的具體實例。

使用對象:
1、創建冰箱的對象
冰箱 bx = new 冰箱();  
2、調用冰箱的功能
對象.功能();
bx.打開();
bx.存儲(new 大象());
bx.關閉();
總結:
1、先按照名詞提煉問題領域中的對象
2、對對象進行描述,其實就是在明確對象中應該具備的屬性和功能
3、通過new的方式就可以創建該事物的具體對象
4、通過該對象調用它以後的功能。

 對象在代碼中的體現

在分析現實生活中的事物時發現,這些事物都有其具體的特點和功能,這些特點和功能就組成了這個特殊的事物。

描述小汽車。

分析:

事物的特點(屬性):

顏色。

輪胎個數。

事物的(功能)

運行。

 

發現:事物其實就是由特點(屬性)和行爲(功能)組成的。

可以簡單理解:屬性就是數值,其實就是變量;行爲就是功能,就是方法。

小汽車 {

顏色;

輪胎個數;

運行() { }

}

通過計算機語言Java來描述這個事物。

定義類的格式
public class 類名 {
	//可編寫0至n個屬性
    數據類型 變量名1;
    數據類型 變量名2;
	
	//可編寫0至n個方法
	修飾符 返回值類型 方法名(參數){
		執行語句;
}
}
汽車類
public class Car {
	String color;
	int number;

	void run() {
		System.out.println(color + ":" + number);
	}
}

通過代碼的描述,知道類的真正意義就是在描述事物。屬性和功能統稱爲事物中的成員。

事物的成員分爲兩種:成員屬性和成員功能。

成員屬性在代碼中的體現就是成員變量

成員功能在代碼中的體現就是成員方法

把寫好的代碼測試一下。需要一個可以獨立運行類。

創建對象的格式:
類名 對象名 = new 類名();
測試類
public class CarDemo {
	public static void main(String[] args) { 
		/*
		 *  測試:Car類中的run方法。
		 */
		// 1,創建Car的對象。給對象起個名字。
		Car c = new Car();// c是類類型的變量。c指向了一個具體的Car類型的對象。
		// 2,通過已有的對象調用該對象的功能。格式:對象.對象成員;
		// 3,可以該對象的屬性賦值。
		c.color = "red";
		c.number = 4;
		c.run();
	}
}

 對象的內存圖解

經過上面對小汽車的描述,和Java代碼測試,我們雖然可以將生活中的事物使用Java代碼描述出來,但是這些代碼在內存中是如何執行的,接下來我們需要研究下對象在內存的圖解。

接下來就是分析對象在內存中的分配情況。這裏需要畫圖一步一步演示,嚴格按照畫圖流程講解內存對象創建過程。



類和對象的區別

面向對象的編程思想力圖在程序中對事物的描述與該事物在現實中的形態保持一致。爲了做到這一點,面向對象的思想中提出兩個概念,即類和對象。其中,類是對某一類事物的抽象描述,而對象用於表示現實中該類事物的個體。接下來通過一個圖例來抽象描述類與對象的關係,如下圖所示。



在上圖中,可以將玩具模型看作是一個類,將一個個玩具看作對象,從玩具模型和玩具之間的關係便可以看出類與對象之間的關係。類用於描述多個對象的共同特徵,它是對象的模板。對象用於描述現實中的個體,它是類的實例。從上圖中可以明顯看出對象是根據類創建的,並且一個類可以對應多個對象,接下來分別講解什麼是類和對象。

經過前面幾個知識點的學習,基本上掌握了類是用於描述事物的,類中可以定義事物的屬性和行爲。而對象是通過描述的這個類,使用new關鍵字創建出來,通過對象就可以調用該對象具體的屬性和功能了。

 局部變量和成員變量區別

理解清楚了類和對象之後,發現在描述類的屬性和前面學習定義變量差別不大,唯一區別就是位置發生了改變,那麼類中定義的變量,和在方法定義的變量有啥差別呢?

回憶以前學習時變量的定義方式,和位置,以及現在定義類中屬性的特點。總結下面幾點異同

區別一:定義的位置不同

定義在類中的變量是成員變量

定義在方法中或者{}語句裏面的變量是局部變量

區別二:在內存中的位置不同

成員變量存儲在對內存的對象中

局部變量存儲在棧內存的方法中

區別三:聲明週期不同

成員變量隨着對象的出現而出現在堆中,隨着對象的消失而從堆中消失

局部變量隨着方法的運行而出現在棧中,隨着方法的彈棧而消失

區別四:初始化不同

成員變量因爲在堆內存中,所有默認的初始化值

局部變量沒有默認的初始化值,必須手動的給其賦值纔可以使用。


 基本類型和引用類型作爲參數傳遞

引用類型數據和基本類型數據作爲參數傳遞有沒有差別呢?我們用如下代碼進行說明,並配合圖解讓大家更加清晰



基本類型作爲參數傳遞時,其實就是將基本類型變量x空間中的值複製了一份傳遞給調用的方法show(),當在show()方法中x接受到了複製的值,再在show()方法中對x變量進行操作,這時只會影響到show中的x。當show方法執行完成,彈棧後,程序又回到main方法執行,main方法中的x值還是原來的值。


當引用變量作爲參數傳遞時,這時其實是將引用變量空間中的內存地址(引用)複製了一份傳遞給了show方法的d引用變量。這時會有兩個引用同時指向堆中的同一個對象。當執行show方法中的d.x=6時,會根據d所持有的引用找到堆中的對象,並將其x屬性的值改爲6.show方法彈棧。

由於是兩個引用指向同一個對象,不管是哪一個引用改變了引用的所指向的對象的中的值,其他引用再次使用都是改變後的值。


2.封裝

提起封裝,大家並不陌生。前面我們學習方法時,就提起過,將具體功能封裝到方法中,學習對象時,也提過將方法封裝在類中,其實這些都是封裝。

封裝,它也是面向對象思想的特徵之一。面向對象共有三個特徵:封裝,繼承,多態。接下來我們具體學習封裝。

l 封裝表現:

  1、方法就是一個最基本封裝體。

  2、類其實也是一個封裝體。

 從以上兩點得出結論,封裝的好處:

 1、提高了代碼的複用性。

 2、隱藏了實現細節,還要對外提供可以訪問的方式。便於調用者的使用。這是核心之一,也可以理解爲就是封裝的概念。

 3、提高了安全性。

 

 封裝舉例

機箱:

一臺電腦,它是由CPU、主板、顯卡、內存、硬盤、電源等部件組長,其實我們將這些部件組裝在一起就可以使用電腦了,但是發現這些部件都散落在外面,很容造成不安全因素,於是,使用機箱殼子,把這些部件都裝在裏面,並在機箱殼上留下一些插口等,若不留插口,大家想想會是什麼情況。

總結:機箱其實就是隱藏了辦卡設備的細節,對外提供了插口以及開關等訪問內部細節的方式。

 私有private

瞭解到封裝在生活的體現之後,又要回到Java中,細說封裝的在Java代碼中的體現,先從描述Person說起。

描述人。Person

屬性:年齡。

行爲:說話:說出自己的年齡。

class Person {
	int age;
	String name;

	public void show() {
		System.out.println("age=" + age + ",name" + name);
	}
}

public class PersonDemo {
	public static void main(String[] args) {
		// 創建Person對象
		Person p = new Person();
		p.age = -20; // 給Person對象賦值
		p.name = "人妖";
		p.show(); // 調用Person的show方法
	}
}

通過上述代碼發現,雖然我們用Java代碼把Person描述清楚了,但有個嚴重的問題,就是Person中的屬性的行爲可以任意訪問和使用。這明顯不符合實際需求。

可是怎麼才能不讓訪問呢?需要使用一個Java中的關鍵字也是一個修飾符 private(私有,權限修飾符)。只要將Person的屬性和行爲私有起來,這樣就無法直接訪問。

class Person {
	private int age;
	private String name;

	public void show() {
		System.out.println("age=" + age + ",name" + name);
	}
}

年齡已被私有,錯誤的值無法賦值,可是正確的值也賦值不了,這樣還是不行,那腫麼辦呢?按照之前所學習的封裝的原理,隱藏後,還需要提供訪問方式。只要對外提供可以訪問的方法,讓其他程序訪問這些方法。同時在方法中可以對數據進行驗證。

一般對成員屬性的訪問動作:賦值(設置 set),取值(獲取 get),因此對私有的變量訪問的方式可以提供對應的 setXxx或者getXxx的方法。

class Person {
	// 私有成員變量
	private int age;
	private String name;

	// 對外提供設置成員變量的方法
	public void setAge(int a) {
		// 由於是設置成員變量的值,這裏可以加入數據的驗證
		if (a < 0 || a > 130) {
			System.out.println(a + "不符合年齡的數據範圍");
			return;
		}
		age = a; 
	}

	// 對外提供訪問成員變量的方法
	public void getAge() {
		return age;
	}
}

 總結:

類中不需要對外提供的內容都私有化,包括屬性和方法。

以後再描述事物,屬性都私有化,並提供setXxx getXxx方法對其進行訪問。

 注意:私有僅僅是封裝的體現形式而已。

this關鍵字

 成員變量和局部變量同名問題

當在方法中出現了局部變量和成員變量同名的時候,那麼在方法中怎麼區別局部變量成員變量呢?可以在成員變量名前面加上this.來區別成員變量和局部變量

class Person {
	private int age;
	private String name;
	
	public void speak() {
		this.name = "小強";
		this.age = 18;
		System.out.println("name=" + this.name + ",age=" + this.age);
	}
}

class PersonDemo {
	public static void main(String[] args) {
		Person p = new Person();
		p.speak();
	}
}
對象的內存解釋
我們已經學習瞭如何把生活中的事物使用Java代碼描述,接下來我們分析對象在內存中的分配情況。這裏需要畫圖一步一步演示,嚴格按照畫圖流程講解內存對象創建使用過程。
class Person {
	private int age;
	public int getAge() {
		return this.age;
	}
	public void setAge(int age) {
		this.age = age;
	}
}
public class PersonDemo {
	public static void main(String[] args) {
		Person p = new Person();
		p.setAge(30);
		System.out.println("大家好,今年我" + p.getAge() + "歲");
	}
}

下圖爲程序中內存對象的創建使用過程。


程序執行流程說明:

1、 先執行main方法(壓棧),執行其中的 Person p = new Person();

2、 在堆內存中開闢空間,併爲其分配內存地址0x1234,緊接着成員變量默認初始化(age = 0);將內存地址0x1234賦值給棧內中的Person p 變量

3、 繼續執行p.setAge(30)語句,這時會調用setAge(int age)方法,將30賦值爲setAge方法中的“age”變量;執行this.age = age語句,將age變量值30 賦值給成員變量this.age爲30;

4、 setAge()方法執行完畢後(彈棧),回到main()方法,執行輸出語句System.out.println(),控制檯打印p對象中的age年齡值。

l 注意:

l this到底代表什麼呢?this代表的是對象,具體代表哪個對象呢?哪個對象調用了this所在的方法,this就代表哪個對象。

上述代碼中的 p.setAge(30)語句中,setAge(int age)方法中的this代表的就是p對象。

學習this的用法之後,現在做個小小的練習。
需求:在Person類中定義功能,判斷兩個人是否是同齡人
class Person {
	private int age;
	private String name;
	
	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	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;
	}
}


 













發佈了34 篇原創文章 · 獲贊 7 · 訪問量 8648
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章