??今天要說的是 Java 中兩個非常重要的概念——類和對象颤诀。
??什么是類,什么又是對象呢对湃?類是對特定集合的概括描述崖叫,比如,人拍柒,這個類心傀,外在特征上,有名字拆讯,有年齡脂男,能說話,能吃飯等等种呐,這是我們作為人類的相同特征宰翅,那么對象呢?我們口口聲聲說要面向?qū)ο缶幊趟遥墒钦伊诉@么久也沒找到對象汁讼,這還怎么編程(滑稽)。此對象非彼對象阔墩,Java 中的對象是某個具體類的實例嘿架,就好比你和我都是人類這個大類的一個實例個體,也就是說啸箫,我們都是人類的一個具體對象耸彪,我們有各自的名字和年齡。
??那為什么要用類和對象這樣的概念呢忘苛?
??這是一個好問題搜囱,類是從面向過程編程向面向?qū)ο缶幊剔D(zhuǎn)變的產(chǎn)物丑瞧。以前的程序,用 C 語言為例子蜀肘,設(shè)計程序是算法 + 數(shù)據(jù)結(jié)構(gòu)的集合绊汹,先設(shè)計算法,然后再選擇合適的數(shù)據(jù)結(jié)構(gòu)去使用算法扮宠。而現(xiàn)在面向?qū)ο缶幊虅t剛好相反西乖,先選擇合適的數(shù)據(jù)結(jié)構(gòu),再設(shè)計相應(yīng)的算法來解決問題坛增。簡單來說获雕,面向過程注重考慮的是事情該怎么做,采用的是上帝視角來處理事情收捣,而面向?qū)ο笞⒅氐氖鞘虑樵撜l來做届案,里面的主角是各鐘類型的對象。面向過程是由上而下的解決問題罢艾,而面向?qū)ο髣t是由下而上
??來舉一個生動形象的栗子楣颠,雙十一快到了,該準備剁手了咐蚯,那具體的剁手步驟呢童漩?
??面向過程是這樣的:先設(shè)置好預(yù)算 budget,然后選擇商品 A,B,C,D春锋,一個個加入收藏矫膨,等待雙十一,付款期奔,完成侧馅。一步一步有條不紊的進行。各個商品的名稱價格信息分別用兩個字符串?dāng)?shù)組進行存儲和處理呐萌。
??而面向?qū)ο髣t是這樣的:因為需要處理的商品數(shù)據(jù)施禾,因此可以構(gòu)建一個商品類 Goods,商品類有名稱搁胆,鏈接弥搞,價格等屬性,此外還需要進行商品預(yù)算管理渠旁,因此可以構(gòu)建一個購物車類 Cart攀例,對商品進行預(yù)算進行統(tǒng)計管理,添加商品顾腊,刪除商品等方法粤铭,然后再設(shè)置一個 Money 類來對財務(wù)進行統(tǒng)一管理,有設(shè)置預(yù)算杂靶,支付等方法梆惯,構(gòu)建好這幾個類之后酱鸭,需要做的就是新建商品對象,往購物車里添加商品對象垛吗,然后等待雙十一凹髓,付款,完成怯屉。
??面向?qū)ο蟮乃枷胫形狄ǎ黧w是對象,通過對象與對象之間的交互來解決問題锨络,就像上面那樣赌躺,關(guān)注的是商品等對象,而面向過程則關(guān)注的是如何解決問題羡儿,即如何在預(yù)算范圍內(nèi)買到合適的商品礼患。
??當(dāng)然,你也許會說掠归,這樣一看缅叠,似乎面向?qū)ο蟾訌?fù)雜也更加麻煩,對于簡單的問題拂到,確實如此,因為面向?qū)ο蟮某霈F(xiàn)本身是為了解決那些復(fù)雜的項目码泞,并提供更好的維護方法兄旬。所以往往越是復(fù)雜的問題,越能體現(xiàn)出面向?qū)ο蟮膬?yōu)越性余寥。那問題來了领铐,既然如此,我舉上面那個栗子來打臉干嘛呢宋舷?绪撵??切莫著急祝蝠,等說完后面的內(nèi)容音诈,最后再來回過頭看看這個問題,就知道怎么回事了绎狭。
??那現(xiàn)在來看看 Java 中的類到底是什么樣的细溅,按慣例先舉個小栗子:
class Goods{
String title;
double price;
}
??這里定義了一個最簡單的類,因為僅做示例用儡嘶,它實際上并沒有什么卵用喇聊,只是為了說明類的一般定義方式,即 class + 類名后面再接大括號蹦狂,在大括號里面寫上類的屬性及方法誓篱。這里的 title 跟 price 都是在類中定義的朋贬,也叫做類成員變量,一般在類的最前端定義我們需要關(guān)注的數(shù)據(jù)變量或者對象窜骄,這一部分也稱為類的實例域锦募。類定義好了,我們需要使用的話怎么使用呢啊研?這時候需要用到 new 關(guān)鍵字來創(chuàng)建類的實例御滩,也就是對象。
public class Test{
public static void main(String[] args) {
Goods goodsA = new Goods();
goodsA.price=1.1;
goodsA.title="123";
System.out.println(goodsA.price);
}
}
class Goods{
String title;
double price;
}
??這里是在同一個文件下定義和使用類党远,而實際上削解,為了便于管理,通常把每個類放到單獨的文件中沟娱,并用類名來定義文件名氛驮,比如 Goods 類放到 Goods.java 文件中,而 Test 則放在 Test.java 文件中济似,那一個文件中引用另一個文件中定義的類撬统,會不會報錯呢?答案是不會的纳猫,編譯器會自動幫我們尋找虱岂,只要按規(guī)范書寫類名及文件名即可。當(dāng)然使用 IDE 的話台舱,在開頭會聲明類所屬的包律杠,關(guān)于包的概念在之前已有闡述,這里就不做過多介紹了竞惋。編譯器會自動在包中尋找相應(yīng)的類柜去。但是需要在 Goods 的定義前加上 public 關(guān)鍵字,表示可以被外部類調(diào)用拆宛。如果需要使用其他包中的類嗓奢,則需要使用 import 關(guān)鍵字來導(dǎo)入類,如浑厚,import java.util.*股耽;這里的 * 代表導(dǎo)入 java.util 下的所有類,導(dǎo)入之后就能像一般類一樣正常使用了钳幅。
??現(xiàn)在定義的類豺谈,只有屬性,沒有方法贡这,看起來就像是一個將兩個數(shù)據(jù)捆綁在一個類中而已茬末,就像 C 語言中的 struct。接下來,我們要擴展這個類丽惭。
??首先击奶,我們需要初始化我們的商品標題和價格,這里為了用做介紹责掏,強行使用了初始化塊(滑稽)柜砾。
public class Goods{
String title;
double price;
{
title = "";
price = 0.0;
}
}
??初始化塊,顧名思義换衬,就是專門用做初始化的代碼塊痰驱,會在類初始化的時候先于構(gòu)造器運行,因為某些變量的初始化并不是賦值這么簡單瞳浦,需要經(jīng)過一些騷操作才能實現(xiàn)担映,而如果放到構(gòu)造器中,會顯得臃腫叫潦,特別是有多個構(gòu)造器的時候蝇完。所以這里的初始化塊是大材小用系列。完全可以寫成以下形式矗蕊,這里只是為了介紹初始化塊而強行加上的內(nèi)容短蜕。
public class Goods{
String title=”“;
double price=0.0;
}
??接下來加上一個構(gòu)造器,什么是構(gòu)造器傻咖?就是構(gòu)造這個類的一個特殊方法朋魔,每個類都至少有一個構(gòu)造器。那上面的栗子不是沒有嗎卿操?事實上警检,如果沒有顯式的添加構(gòu)造器方法,系統(tǒng)會提供一個默認的無參構(gòu)造器硬纤,但是這個構(gòu)造器什么也不做解滓,所以才會毫無存在感≡吣ィ現(xiàn)在我們要賦予它神圣的使命筝家,讓它變得有價值起來。
public class Goods{
String title="";
double price=0.0;
public Goods(String aTitle,double aPrice){
title = aTitle;
price = aPrice;
}
}
??構(gòu)造器的名稱跟類名一致邻辉,前面加上 public 修飾符溪王,小括號內(nèi)是參數(shù)列表,這里用了兩個參數(shù)值骇,分別用來指定類的 title 跟 price 信息莹菱。這樣,之前 Test 類就可以這樣寫了吱瘩。
public class Test{
public static void main(String[] args) {
Goods goodsA = new Goods("123",1.1);
System.out.println(goodsA.price);
}
}
??這樣使用起來是不是更加簡單粗暴道伟,一般的簡單初始化代碼也會放到構(gòu)造器中進行。我們還可以定義多個構(gòu)造器。
public class Goods{
String title="";
double price=0.0;
public Goods(String aTitle,double aPrice){
title = aTitle;
price = aPrice;
}
public Goods(double aPrice){
price = aPrice;
title = "Goods";
}
}
public class Test{
public static void main(String[] args) {
Goods goodsA = new Goods("notebook",1.1);
Goods goodsB = new Goods(2.2);
System.out.println("goodsA title:"+goodsA.title+" price:"+goodsA.price);
System.out.println("goodsB title:"+goodsB.title+" price:"+goodsB.price);
}
}
??這樣既可以使用兩個參數(shù)的構(gòu)造器蜜徽,也可以使用只有一個參數(shù)的構(gòu)造器祝懂,會執(zhí)行不同的構(gòu)造器方法。
??構(gòu)造器有了拘鞋,接下來加上兩個方法砚蓬,用于讀取價格和標題,以及設(shè)置價格和標題盆色。
public class Goods{
private String title="";
private double price=0.0;
public Goods(String aTitle,double aPrice){
title = aTitle;
price = aPrice;
}
public Goods(double aPrice){
price = aPrice;
title = "Goods";
}
public String getTitle(){
return title;
}
public double getPrice(){
return price;
}
public void setTitle(String aTitle){
title = aTitle;
}
public void setPrice(double aPrice){
price = aPrice;
}
}
??這樣我們的類就已經(jīng)很豐滿灰蛙,呸,飽滿了隔躲。這里我們添加了四個方法摩梧,兩個方法用于讀取成員變量,兩個方法用于設(shè)置成員變量蹭越,此外障本,我們還將兩個成員變量設(shè)置成了 private,這樣這兩個成員變量就只能在類的內(nèi)部的方法中使用响鹃,在其他類中是禁止使用的驾霜。你可能會問,為什么要弄的這樣復(fù)雜呢买置,兩個數(shù)據(jù)直接操作不好嗎粪糙?這就是封裝的意義了,把數(shù)據(jù)完全封裝在類里忿项,只開放接口進行訪問和修改蓉冈,這樣類就像一個插座一樣,外部代碼不需要知道插座里面是什么東西轩触,只需要知道這是三孔插座還是兩孔插座寞酿,知道怎樣使用就可以了,這樣的好處在于脱柱,可以很方便的進行維護伐弹,因為數(shù)據(jù)形式是容易改變的,但只要提供的接口不改變榨为,其他代碼就不需要改變惨好,降低代碼之間的依賴程度,這樣就能實現(xiàn)模塊化的效果随闺。
??那現(xiàn)在 Test 類也需要做相應(yīng)調(diào)整了日川,因為 Goods 類成員已經(jīng)聲明為 private 了,所以只能通過類方法來進行訪問矩乐。通常把用與訪問類成員的方法叫做訪問器龄句,設(shè)置類成員的方法叫做更改器。
public class Test{
public static void main(String[] args) {
Goods goodsA = new Goods("notebook",1.1);
Goods goodsB = new Goods(2.2);
System.out.println("goodsA title:"+goodsA.getTitle()+" price:"+goodsA.getPrice());
System.out.println("goodsB title:"+goodsB.getTitle()+" price:"+goodsB.getPrice());
}
}
??好了,現(xiàn)在我們的類變得有些厲害了分歇,那如果現(xiàn)在需要將商品鏈接也加進去透葛,該怎么辦呢?
public class Goods{
private String title="";
private double price=0.0;
private String link = "";
public Goods(String aTitle,double aPrice,String aLink){
title = aTitle;
price = aPrice;
link = aLink;
}
public Goods(String aTitle,double aPrice){
title = aTitle;
price = aPrice;
link = "www.baidu.com";
}
public Goods(double aPrice){
price = aPrice;
title = "Goods";
link = "www.baidu.com";
}
public String getTitle(){
return title;
}
public double getPrice(){
return price;
}
public String getLink() {
return link;
}
public void setTitle(String aTitle){
title = aTitle;
}
public void setPrice(double aPrice){
price = aPrice;
}
public void setLink(String aLink){
link = aLink;
}
}
??加上一個成員變量卿樱,再加上相應(yīng)的訪問器和更改器即可僚害,當(dāng)然,這里新增了一個構(gòu)造器繁调,這樣的話萨蚕,不僅之前的代碼仍可以使用,還能使用新方法蹄胰,騷出新高度岳遥。
public class Test{
public static void main(String[] args) {
Goods goodsA = new Goods("notebook",1.1);
Goods goodsB = new Goods(2.2);
Goods goodsC = new Goods("Java class",233,"www.cnblogs.com/mfrank/p/7747587.html");
System.out.println("goodsA title:"+goodsA.getTitle()+" price:"+goodsA.getPrice()+" link:"+goodsA.getLink());
System.out.println("goodsB title:"+goodsB.getTitle()+" price:"+goodsB.getPrice()+" link:"+goodsB.getLink());
System.out.println("goodsC title:"+goodsC.getTitle()+" price:"+goodsC.getPrice()+" link:"+goodsC.getLink());
}
}
??這樣就能輸出三個對象的所有信息了,等等裕寨,不覺得輸出的時候太麻煩了嗎浩蓉,重復(fù)三次及以上的地方就需要考慮用一個函數(shù)來代替。嗯宾袜,來給我們的 Goods 類加上一個輸出方法捻艳。
public class Goods{
private String title="";
private double price=0.0;
private String link = "";
public Goods(String aTitle,double aPrice,String aLink){
title = aTitle;
price = aPrice;
link = aLink;
}
public Goods(String aTitle,double aPrice){
title = aTitle;
price = aPrice;
link = "www.baidu.com";
}
public Goods(double aPrice){
price = aPrice;
title = "Goods";
link = "www.baidu.com";
}
public String getTitle(){
return title;
}
public double getPrice(){
return price;
}
public String getLink() {
return link;
}
public void setTitle(String aTitle){
title = aTitle;
}
public void setPrice(double aPrice){
price = aPrice;
}
public void setLink(String aLink){
link = aLink;
}
public void print(){
System.out.println("title:"+title+" price:"+price+" link:"+link);
}
}
public class Test{
public static void main(String[] args) {
Goods goodsA = new Goods("notebook",1.1);
Goods goodsB = new Goods(2.2);
Goods goodsC = new Goods("Java class",233,"www.cnblogs.com/mfrank/p/7747587.html");
goodsA.print();
goodsB.print();
goodsC.print();
}
}
??你看,我們的類定義好之后庆猫,主函數(shù)里的代碼是不是就變得很簡單了认轨。這就是封裝的好處,封裝好以后只需要知道怎樣使用就行了月培,不需要關(guān)注內(nèi)部是怎樣實現(xiàn)的嘁字。
??好了,關(guān)于類與對象的內(nèi)容就說到這了杉畜,總結(jié)一下纪蜒,類是某一特定集合的特征描述,對象是類的具體實例此叠,在使用的時候類的時候纯续,需要用 new 關(guān)鍵字來 new 一個對象,然后才能使用類方法來操作這個對象拌蜘。類可以看作是對象的模版杆烁,就像一個工廠一樣牙丽,可以生成衣服简卧,但每件衣服的款式是可以不一樣的。
??至此烤芦,本篇講解結(jié)束举娩,歡迎大家繼續(xù)關(guān)注。