前言
本篇講解Java類和對象的入門版本。
學習目的:
1.理解什么是類和對象。
2.引入面向對象程序設計的概念
3.學會如何定義類和創建對象。
4.理解this引用。
5.了解構造方法的概念并學會使用考慮到篇幅過長問題,作者決定分多次發布。
面向對象的引入
Java是一門面向對象的程序設計語言。那么面向對象具體是啥意思呢?
面向對象(Object-oriented)更多是一種思維模式,它替換了原有的面向過程的思考方式,轉為了面向對象。這種編程思想強調了將問題分解為對象的集合,對象有各自的屬性和方法,對象與對象之間又有信息傳遞和行為協助。
- 總結:解決問題的重心由拆分步驟,改變成拆分成對象,對象和對象的協作上。編程思維模式的轉變
面向過程編程
如果你先前學過任何一門面向過程的編程語言,比如C語言。回憶一下,先前解決問題是不是研究解決一個問題的過程是怎樣的?
它的重點在于如何完成任務,要實現哪些功能的函數,函數接收參數返回值,執行一系列的邏輯結構過程,然后才是研究數據應該采用什么數據結構存儲,最后輸出正確的結果。
面向過程首先考慮的是如何處理數據即算法,其次是數據如何存儲(數據結構)。
面向對象編程
面向對象編程(Object-Oriented Programming)簡稱OOP.它是一種以對象為中心的編程范式,對象有自己的狀態行為,通過封裝,繼承,多態實現代碼的模塊化。實現對象與對象之間的協作和交互。
與面向過程對比,面向對象先考慮的是數據如何存儲,將相關聯的數據和方法包裝成一個對象。其次考慮處理對象與對象之間。可以說先數據結構后算法,與面向過程反著來了。
生活化的示例
傳統洗衣服(面向過程)
1.拿臟的衣物。
2.水槽裝足夠的水
3.加入洗衣粉
4.將臟衣服放入水槽
5.瘋狂手搓
6.沖洗衣服
7.換水
8.繼續沖洗衣服
9.擰干洗好的衣服
10.晾衣服。
現代洗衣服(面向對象)
確定對象 臟衣物,洗衣粉,洗衣機
我們人為交互
1.將臟衣物放入洗衣機
2.倒入洗衣粉。
3.設定洗衣機的程序。
洗完后,取出晾干就可以了。
整個都是三個對象的交互。洗衣機怎么洗的,內部怎么運作的?I don’t care.
總之我知道按照上面三步衣服就洗好了。
類和對象的概念
舉個栗子,人就是一個類。人有姓名,年齡,身高,體重,家庭住址。但人的概念太抽象了,太廣泛了。那么張三,小紅,李華,你和我,就是具體的人了,我們也有上面的姓名身高年齡。
所以呢,*類是類型,藍圖,模板。*即上面例子中的人。那么后面的張三就是具體的人,就稱為一個對象。人有的屬性,張三也有。
所以,類可以描述對象,對象是類的實例化。
類
接下來正式介紹類
類(class)是構造( construct ) 對象的模板和藍圖, 由類構造對象的過程稱為創建類的實例 ( instance ) 。
現在籠統的闡述類的特點,后面補充實例
類的特點:
1.屬性(fileds):類可以定義成員變量。成員變量體現的是對象的屬性(狀態特征)。每個對象通過各自類的屬性有自己的特點狀態。
2.方法(methods):類內部可以定義成員方法,簡稱方法或者函數。方法定義了對象的行為,方法可以讓對象執行某種特定的功能,更能完成對象與對象的協作。
3.類的實例化(instance):類本身只是一個模板,類似C中的結構體。只有實例化(構造對象),它內部的屬性和方法才有意義。如何創建下面會給出例子。
4.構造方法(construct):這里先不提,往后看下去,后面會講。
5.封裝類,抽象類,繼承,接口…………這里不提。其實作者也沒懂完
現在可以定義一個類了
類的基本語法(目前掌握以下這些就夠了)
class 類名{
//屬性:成員變量//成員方法
}
1.class 類的關鍵字,定義一個類必須有。
2.類名:遵循標識符的命名規則,采用大駝峰命名法。
3.花括號別忘了,別漏了。
4.屬性(成員變量):這里可以定義各種類型變量表示類的狀態了。
5.成員方法:定義類的行為與操作。
下面定義一個Dog類
public class Dog {
//成員變量public String name;public int age;//成員方法public void bark(){System.out.println("Ruff! Ruff!");}
}
上面我們定義這樣一個類,該類有兩個成員變量,分別是字符串name和int年齡。還有bark這樣一個成員方法表示dog在叫的行為。
這里的public是訪問修飾符,表示類,成員變量,成員方法的訪問權限。
類的實例化
由類生成對象的過程叫做類的實例化
類在Java中為引用類型。
int double float為內置類型(基本數據類型),Java中與其相對的類型稱為引用類型,數組字符串也是引用類型。引用類型也是自定義類型,類是用戶自定義出來的類型。
Java中由類創建一個對象,要用到關鍵字new.
Dog dog=new Dog();
語法:
類名 變量名 = new 類名()
這里Dog就是先前定義的類了。
dog是這個類類型的變量名。
new “給我一個對象” 后面跟上Dog()就創建了一個屬于Dog的對象了。
new后面其實跟著的是構造方法,這個稍后再說。
既然創建了對象,我們定然想到如何處理對象呢。
dog.age=1;dog.name="Bin";dog.bark();
通過圓點運算符(.)我們就可以訪問對象的成員了和方法了。
這里對象繼承了類的屬性,這個實例化的dog也有了name和age,也能調用bark()方法了。
假設我們不對對象初始化操作,會出現問題嗎?
不會,因為局部變量未初始化會被編譯器報錯警告。而對象的成員變量不在棧上而在堆上,未初始化會有對應的默認值。
Dog dog=new Dog();System.out.println(dog.name);System.out.println(dog.age);
對于引用類型,其默認值為null;內置類型就為相應的0值,int對于0,float對應0.0F,double對應0.0,另外boolean對應false。
我這里的dog在main方法內部創建,就是局部變量在棧上開辟一塊空間,同時在堆上為這個對象開辟合適的空間保存對象的屬性。這里的dog實際存儲了對象在堆上的地址,dog就稱為一個引用。通過引用,我們訪問對象的成員。
對象
其實類那一部分已經說明完大部分對象的內容,這里稍作補充和總結。
對象有狀態。這里的狀態從代碼來看就是成員變量的值不同,反過來就算同一個類的對象成員變量的值不同說明他們之間狀態不同。
對象有行為。根據對象的狀態,調用成員方法行為上不同,反之根據自身的行為(方法調用)也會影響自身狀態。
對象有名字。每個對象應該有獨立的標識符來區分不同
對象與對象之間獨立。每個對象有自己的狀態和行為。
認識this引用
關鍵字this
先定義如下一個類
里面的setData成員方法中的形參與成員變量名同名還能進行賦值嗎?
public class Date {public int year;public int month;public int day;public void setDate(int year,int month,int day){year=year;month=month;day=day;}public void printByString(){System.out.println("year = "+year+" month = "+ month+" day = "+ day);}
}
public class Date {public int year;public int month;public int day;public void setDate(int year,int month,int day){year=year;month=month;day=day;}public void printByString(){System.out.println("year = "+year+" month = "+ month+" day = "+ day);}public static void main(String[] args) {Date date=new Date();date.setDate(2024,5,13);date.printByString();}
}
運行結果是怎樣的呢?修改data對象的值了嗎?
答案必然是沒有!否則這里要說明的this干嘛呢。
很明顯,這里setDate里形參和成員變量名重復了,左值的year究竟代表了成員變量還是形參呢?是形參。
所以,這里上述的賦值就是自我娛樂,對成員變量沒有影響。因為調用方法時會在棧上開辟空間稱作函數棧幀,此時局部變量(函數形參)優先使用。
這個時候就要用上this對setDate函數做出如下修改。
public void setDate(int year,int month,int day){this.year=year;this.month=month;this.day=day;}
這里的this相當于原來的date對象,很顯然this.成員變量和方法參數區分開了。說明了這里左值同名的year,month,day是引用(data對象)的成員變量。避免出現同名時混淆的情況。
那么this是怎樣知道它代表哪個引用呢?
實際上那個對象的引用在某個方法時會將這個引用當作函數參數傳遞過去。
實際的setDate寫成下面這樣。只不過我們寫的時候省略了第一個參數罷了。
由此我們可以知道那個對象的引用在調用某方法時,這個this就代表誰了。
public void setDate(Date this,int year,int month,int day){this.year=year;this.month=month;this.day=day;}
這里的this由于就是date,它也可以調用自身的成員方法。
public class Date {public int year;public int month;public int day;public void setDate(Date this,int year,int month,int day){this.year=year;this.month=month;this.day=day;this.printByString();}public void printByString(){System.out.println("year = "+year+" month = "+ month+" day = "+ day);}public static void main(String[] args) {Date date=new Date();date.setDate(2024,5,13);}
}
this還有一個用處調用其它構造方法
構造方法
前面提過成員方法,那么構造方法和成員方法有什么區別呢?類比學習一下吧。
一般的成員方法格式:
返回值 方法名(參數列表){
//方法體
}
構造方法可以看作特殊的成員方法
第一,它沒有返回值類型。
第二,它的方法名和它的類名一樣。
即
構造方法格式:
返回值方法名類名(參數列表){
//方法體
}
public Date(){}
這就是一個簡單的構造方法。
想到前面這個Date date=new Date();
new后面的 Date()不就是一個構造方法嗎?哎奇怪,當時我們并沒有創建這樣的構造方法呀。
事實上,如果定義的類沒有構造方法,編譯器會默認給你上述的構造方法,這種構造方法是最簡單的。沒有帶任何參數。
需要注意的是,如果你自己創造了一個構造方法,請嚴格按照你的構造方法創建對象,此時編譯器不會在為你默認這么一個構造方法了。
下面給出一個帶參數形式的構造方法。
public Date(int year,int month,int day){this.year=year;this.month=month;this.day=day;}
這樣就可以在創建對象時同時初始化成員變量了。
構造方法同樣支持重載。即上面兩個構造方法可以同時存在一個Date類中。
public class Date {public int year;public int month;public int day;public void setDate(Date this,int year,int month,int day){this.year=year;this.month=month;this.day=day;this.printByString();}public void printByString(){System.out.println("year = "+year+" month = "+ month+" day = "+ day);}public Date(){}public Date(int year,int month,int day){this.year=year;this.month=month;this.day=day;}public static void main(String[] args) {Date date=new Date(2004,12,8);date.printByString();}
}
最后總結一下構造方法:
1.構造方法名與類名相同。
2.無返回值類型,不要理解成返回值類型為void
3.創建對象時調用,且只能調用一次。
4.構造方法可以重載。(比如上面的構造方法在創建對象時可以選擇不帶參數,還可以選三個參數初始化的)
5.如果沒有自定義構造方法,那么編譯器默認會構造方法。
結尾
想不出來說什么了,太困了。嗯~
一無所有,或者贏下所有