類與對象
對象在需求中的使用
對面向對象有了了解之后,我們來說說在具體問題中如何使用面向對象去分析問題,和如何使用面向對象。
我們把大象裝冰箱為例進行分析。
在針對具體的需求,可以使用名詞提煉的辦法進行分析,尋找具體的對象。
需求:把大象裝冰箱里
對象:大象、冰箱
分三步:
1、打開冰箱門
2、將大象裝進去
3、關閉冰箱門
分析發現打開、裝、關閉都是冰箱的功能。即冰箱對象具備如下功能:
冰箱打開
冰箱存儲
冰箱關閉
用偽代碼描述,上述需求中有兩個具體的事物 大象 和 冰箱
描述大象:
class 大象
{
void 喝水(){}
}
描述冰箱
class 冰箱
{
void 打開(){}
void 存儲(大象){}
void 關閉(){}
}
當把具體的事物描述清楚之后,需要使用這些具體的事物,Java使用具體的事物,需要通過new關鍵字來創建這個事物的具體實例。
使用對象:
1、創建冰箱的對象
冰箱 bx = new 冰箱();
2、調用冰箱的功能
對象.功能();
bx.打開();
bx.存儲(new 大象());
bx.關閉();
總結:
1、先按照名詞提煉問題領域中的對象
2、對對象進行描述,其實就是在明確對象中應該具備的屬性和功能
3、通過new的方式就可以創建該事物的具體對象
4、通過該對象調用它以后的功能。
對象的內存圖解
經過上面對小汽車的描述,和Java代碼測試,我們雖然可以將生活中的事物使用Java代碼描述出來,但是這些代碼在內存中是如何執行的,接下來我們需要研究下對象在內存的圖解。
接下來就是分析對象在內存中的分配情況。這里需要畫圖一步一步演示,嚴格按照畫圖流程講解內存對象創建過程。
類和對象的區別
面向對象的編程思想力圖在程序中對事物的描述與該事物在現實中的形態保持一致。為了做到這一點,面向對象的思想中提出兩個概念,即類和對象。其中,類是對某一類事物的抽象描述,而對象用於表示現實中該類事物的個體。接下來通過一個圖例來抽象描述類與對象的關系,如下圖所示。
在上圖中,可以將玩具模型看作是一個類,將一個個玩具看作對象,從玩具模型和玩具之間的關系便可以看出類與對象之間的關系。類用於描述多個對象的共同特征,它是對象的模板。對象用於描述現實中的個體,它是類的實例。從上圖中可以明顯看出對象是根據類創建的,並且一個類可以對應多個對象,接下來分別講解什么是類和對象。
經過前面幾個知識點的學習,基本上掌握了類是用於描述事物的,類中可以定義事物的屬性和行為。而對象是通過描述的這個類,使用new關鍵字創建出來,通過對象就可以調用該對象具體的屬性和功能了。
局部變量和成員變量區別
理解清楚了類和對象之后,結合前5天的學習知識,發現在描述類的屬性和前面學習定義變量差別不大,唯一區別就是位置發生了改變,那么類中定義的變量,和在方法定義的變量有啥差別呢?
回憶以前學習時變量的定義方式,和位置,以及現在定義類中屬性的特點。總結下面幾點異同
區別一:定義的位置不同
定義在類中的變量是成員變量
定義在方法中或者{}語句里面的變量是局部變量
區別二:在內存中的位置不同
成員變量存儲在堆內存的對象中
局部變量存儲在棧內存的方法中
區別三:聲明周期不同
成員變量隨着對象的出現而出現在堆中,隨着對象的消失而從堆中消失
局部變量隨着方法的運行而出現在棧中,隨着方法的彈棧而消失
區別四:初始化不同
成員變量因為在堆內存中,所有默認的初始化值
局部變量沒有默認的初始化值,必須手動的給其賦值才可以使用。
基本類型和引用類型作為參數傳遞
引用類型數據和基本類型數據作為參數傳遞有沒有差別呢?我們用如下代碼進行說明,並配合圖解讓大家更加清晰
class Demo
{
public static void main(String[] args)
{
int x = 4;
show(x);
System.out.println("x="+x);
}
public static void show(int x)
{
x = 5;
}
}
基本類型作為參數傳遞時,其實就是將基本類型變量x空間中的值復制了一份傳遞給調用的方法show(),當在show()方法中x接受到了復制的值,再在show()方法中對x變量進行操作,這時只會影響到show中的x。當show方法執行完成,彈棧后,程序又回到main方法執行,main方法中的x值還是原來的值。
class Demo
{
int x ;
public static void main(String[] args)
{
Demo d = new Demo();
d.x = 5;
show(d);
System.out.println("x="+d.x);
}
public static void show(Demo d)
{
d.x = 6;
}
}
當引用變量作為參數傳遞時,這時其實是將引用變量空間中的內存地址(引用)復制了一份傳遞給了show方法的d引用變量。這時會有兩個引用同時指向堆中的同一個對象。當執行show方法中的d.x=6時,會根據d所持有的引用找到堆中的對象,並將其x屬性的值改為6.show方法彈棧。
由於是兩個引用指向同一個對象,不管是哪一個引用改變了引用的所指向的對象的中的值,其他引用再次使用都是改變后的值。
封裝
封裝概述
提起封裝,大家並不陌生。前面我們學習方法時,就提起過,將具體功能封裝到方法中,學習對象時,也提過將方法封裝在類中,其實這些都是封裝。
封裝,它也是面向對象思想的特征之一。面向對象共有三個特征:封裝,繼承,多態。接下來我們具體學習封裝。
封裝表現:
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年齡值。
注意:
this到底代表什么呢?this代表的是對象,具體代表哪個對象呢?哪個對象調用了this所在的方法,this就代表哪個對象。
上述代碼中的 p.setAge(30)語句中,setAge(int age)方法中的this代表的就是p對象。
this的應用
學習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;
}
}
總結
類與對象
類,用於描述多個對象的共同特征,它是對象的模板。
對象,用於描述現實中的個體,它是類的實例。
類的定義:使用關鍵字class來定義java中的類
格式:
class 類名 {
//屬性
數據類型 變量名;
…
//方法
修飾符 返回值類型 方法名(參數){ }
…
}
創建對象:
格式:
類名 對象名 = new 類名();
封裝(private關鍵字)
封裝,把對象的屬性與方法的實現細節隱藏,僅對外提供一些公共的訪問方式
封裝的體現:
變量:使用 private 修飾,這就是變量的封裝
方法:也是一種封裝,封裝了多條代碼
類: 也是一種封裝,封裝了多個方法
private 關鍵字,私有的意思
它可以用來修飾類中的成員(成員變量,成員方法)
private 的特點:
private 修飾的成員只能在當前類中訪問,其他類中無法直接訪問
this 關鍵字
this 關鍵字,本類對象的引用
this 是在方法中使用的,哪個對象調用了該方法,那么,this 就代表調用該方法的對象引用
this 什么時候存在的?當創建對象的時候,this 存在的
this 的作用:用來區別同名的成員變量與局部變量(this.成員變量)
public void setName(String name) {
this.name = name;
}