Java 類和對象
經過前面一系列的學習,你可能對類和對象已經有了一定的了解,這是因為 Java 語言是純面向對象的編程語言,類和對象在 Java 中無處不在。
在程序設計時,我們針對事物的特征和行為使用代碼進行實現,就是面向對象編程。可以毫不夸張地說,面向對象編程是中大型項目代碼最好的組織形式。
本小節我們將學習類和對象的基本概念、類和對象的關系,除了字段和方法,在類中都可以定義什么其他內容。也會講解什么是實例化、實例化過程是怎樣的,構造方法是什么,如何定義以及其特點,this
關鍵字的含義和使用。
1. 類和對象
1.1 什么是類
我們在前面的學習中已經知道,類 (class) 是一個程序的基本單位,我們之前所編寫的 .java
文件都是類。在現實生活中,慕課網學生可以是一個類、交通工具可以是一個類、NBA 球員可以是一個類。例如,如下代碼聲明了一個慕課網學生類:
public class ImoocStudent {
...
}
1.2 什么是對象
你也許聽到過一句話:“萬物皆對象”。是的,現實世界中所有的事物,都可以是對象。例如一個慕課網學生、一輛汽車、NBA 巨星喬丹等等,都是對象。 對象是具體的一個事物。下面我們來看一下類和對象的關系。
1.3 類和對象的關系
類是一個抽象的概念,可以將它理解成 “模板”,可用于產生對象;而對象是一個具體的事物。
ImoocStudent
是一個類,毋庸置疑,它是抽象的,不能表示一個具體的事物;而屏幕面前的你作為慕課網學生,就是一個對象,因為你是實實在在的、具體的一個慕課網學生,和你一樣的在慕課網學習的其他同學,都可以理解為是由 ImoocStudent
類產生的一個個具體的對象。
例如,很多 NBA 球星:科比、喬丹、詹姆斯等他們都是具體的球員,具體的球員就是對象,而這樣一組對象在代碼中可以抽象為類。
2. 定義類
定義類的語法,相信大家都已經熟練掌握,下面我們就以慕課網學生為例,初步抽象出一個簡單的慕課網學生類。
Tips:在本小節的剩余內容中,我們都將圍繞這個例子展開學習。下面請跟上節奏認真思考。
2.1 慕課網學生類
在代碼中,事物的靜態特征被抽象成屬性,事物的動態行為被抽象成方法。一個基本的慕課網學生類可以包含若干屬性和方法。
慕課網學生可以有昵稱、職位、城市、性別等特征,如下是慕課網個人中心的截圖:

除了這些特征,還可以有學習課程、評論、發表手記等行為。有了這些特征和行為,我們就可以抽象出一個慕課網學生類:
public class ImoocStudent {
// 定義屬性(特征)
String nickname; // 昵稱
String position; // 職位
String city; // 城市
String sex; // 男 | 女
// 定義方法(行為)
public void studyCourse() {
System.out.println("學習課程");
}
public void postComment() {
System.out.println("發表評論");
}
public void postArticle() {
System.out.println("發表手記");
}
}
2.2 組成類的元素
Tips:類組成元素屬于擴展內容,此處有一個整體認識即可。隨著面向對象的深入學習,知識點都會涵蓋。
剛剛我們通過對現實生活中慕課網學生的分析,抽象出了慕課網學生類,并在類中定義了一些屬性和方法。那么除了屬性和方法,類中還可以有什么其他元素呢?
下面我們來詳細介紹,每個類都可以由以下元素組成:
- 成員屬性:也稱為字段,成員變量或實例變量,屬性是用以保存每個對象的數據的變量,例如每個慕課網學生都可能有昵稱、性別等。每個對象之間的屬性相互獨立,互不干擾;
- 成員方法:也稱實例方法,成員方法是對對象執行的操作,例如,一個慕課網學生有一種方法來進行發表評論;
- 靜態變量:也稱為類屬性,它是同一個類的任何對象所共有的。例如,一個慕課網學生類中的最后一個被添加的學生 ID,可以用靜態變量標記。 一個類不管被實例化了多少對象,每個靜態變量在類中僅存在一次;
- 靜態方法:也稱為類方法,靜態方法是不影響特定對象的方法;
- 內部類:可以將一個類包含在另一個類中,常用于該類僅提供給聲明它的類使用的情況;
- 構造方法:生成新對象的特殊方法;
- 參數化類型:可以在定義期間將參數化類型分配給類。 參數化類型將替換為在類實例化時指定的類型。 它由編譯器完成。 它類似于 C 語言宏
#define
語句,其中預處理器評估宏。
3. 對象的實例化
3.1 創建對象
上面我們已經定義了慕課網學生類,有了類就可以產生對象了。這里的產生對象指的就是對象的實例化操作,在 Java 中,使用 new
關鍵字實例化對象,其語法為:
類名 對象名稱 = new 類名();
類是對象的類型,因此我們以類名作為對象類型,對象名稱的命名規范與變量相同。例如,實例化一個慕課網學生對象,對象名稱命名為 student
:
ImoocStudent student = new ImoocStudent();
關于對象的實例化過程,可以分為兩部分:
- 聲明對象:在內存的??臻g中執行。
ImoocStudent student;
- 實例化對象:在內存的堆空間執行。
new ImoocStudent();
3.2 調用屬性和方法
對象實例化后,可以調用其屬性和方法,其語法為:
// 調用屬性
對象名.屬性名;
// 調用方法
對象名.方法名();
下面我們在 ImoocStudent
類的主方法中實例化一個慕課網學生對象,并依次調用其屬性和方法:
public class ImoocStudent {
// 定義屬性(特征)
String nickname; // 昵稱
String position; // 職位
String city; // 城市
String sex; // 男 | 女
// 定義方法(行為)
public void studyCourse() {
System.out.println("學習課程");
}
public void postComment() {
System.out.println("發表評論");
}
public void postArticle() {
System.out.println("發表手記");
}
public static void main(String[] args) {
// 實例化學生對象
ImoocStudent student = new ImoocStudent();
// 調用并打印成員屬性
System.out.println("昵稱:" + student.nickname);
System.out.println("職位:" + student.position);
System.out.println("城市:" + student.city);
System.out.println("性別:" + student.sex);
// 調用成員方法
student.studyCourse();
student.postComment();
student.postArticle();
}
}
運行結果:
昵稱:null
職位:null
城市:null
性別:null
學習課程
發表評論
發表手記
根據運行結果,我們看到了成員屬性和成員方法都被成功調用。但所有的屬性值都為 null
,這是因為成員屬性沒有默認值,系統會給一個默認初值。
Tips:不同數據類型的屬性會有不同的初值。此例中的屬性,都為字符串,默認初值為
null
,你也可以嘗試為ImoocStudent
類添加其他類型的屬性,來看看它們各自的默認初值。這里不再一一演示。
3.3 給屬性賦值
給成員屬性賦值的語法為:
對象名.屬性名 = 屬性值;
下面我們來修改一下在主方法中的代碼:
public class ImoocStudent {
// 定義屬性(特征)
String nickname; // 昵稱
String position; // 職位
String city; // 城市
String sex; // 男 | 女
// 定義方法(行為)
public void studyCourse() {
System.out.println("學習課程");
}
public void postComment() {
System.out.println("發表評論");
}
public void postArticle() {
System.out.println("發表手記");
}
public static void main(String[] args) {
// 實例化學生對象
ImoocStudent student = new ImoocStudent();
// 給成員屬性賦值
student.nickname = "Colorful";
student.position = "服務端工程師";
student.city = "北京";
student.sex = "男";
// 調用成員屬性
System.out.println("昵稱:" + student.nickname);
System.out.println("職位:" + student.position);
System.out.println("城市:" + student.city);
System.out.println("性別:" + student.sex);
}
}
運行結果:
昵稱:Colorful
職位:服務端工程師
城市:北京
性別:男
4. 構造方法
4.1 概述
在類中,可定義一個構造方法,也稱為構造函數或構造器。它用于一些初始化操作,構造方法的語法為:
public 構造方法名(參數) {
// 代碼塊
}
需要注意的是,與普通的自定義方法不同,構造方法沒有返回類型,并且方法名要與類名同名。
另外,如果我們沒有定義構造方法,系統會有一個默認的構造方法。換句話說:任何一個類都會有一個構造方法。
構造方法只能在對象的實例化時使用,也就是說,構造方法只能配合 new
關鍵字使用。
根據參數的有無,構造方法可分為兩種:
- 無參構造方法
- 有參構造方法
4.2 無參構造方法
在 ImoocStudent
類中,我們可以定義一個無參構造方法:
// 定義構造方法,無返回值并且命名與類名相同
public ImoocStudent() {
// 執行輸出語句
System.out.println("無參構造方法執行了...");
}
使用 new
關鍵字調用構造方法:
ImoocStudent student = new ImoocStudent();
運行結果:
無參構造方法執行了...
4.3 有參構造方法
當創建實例對象時,我們經常需要同時初始化這個實例的成員屬性,例如:
ImoocStudent student = new ImoocStudent();
student.nickname = "慕女神";
student.position = "UI設計師";
雖然這樣能夠給我們的成員屬性進行賦值,但每次需要編寫 2 行這樣的代碼。能不能在創建對象時,就對這些屬性進行賦值呢?有參構造方法解決了這樣的問題,我們可以在 ImoocStudent
類內部定義一個有參構造方法:
// 有參構造方法
public ImoocStudent(String studentNickname, String studentPosition) {
// 將參數變量賦值給實例變量
nickname = studentNickname;
position = studentPosition;
}
構造函數中,我們將參數變量的值賦值給實例變量。使用 new
關鍵字調用構造方法:
ImoocStudent student1 = new ImoocStudent("慕女神", "UI設計師");
System.out.println("昵稱為:" + student1.nickname);
System.out.println("職位為:" + student1.position);
運行結果:
昵稱為:慕女神
職位為:UI設計師
你也可以增加構造函數的參數數量,以用來給更多的實例屬性賦值:
// 有參構造方法
public ImoocStudent(String studentNickname, String studentPosition, String studentCity, String studentSex) {
nickname = studentNickname;
position = studentPosition;
city = studentCity;
sex = studentSex;
}
構造方法與普通方法相同,也會重載,因此類中允許定義多個參數列表不同構造方法。
需要特別注意的是,我們在上面兩個有參構造方法中,成員屬性的命名和參數變量的命名是不同的,如果參數列表中參數變量的命名和實例屬性相同。將無法完成對實例屬性的賦值,也就是說,下面的寫法是錯誤的:
public ImmocStudent(String nickname) {
nickname = nickname;
}
這是因為構造方法在參數的賦值過程中,會優先到同一個作用范圍內的 nickname
進行賦值操作,這就是所謂的就近原則。這時我們可以使用 this
關鍵字。
5. this 關鍵字
為了解決上面無法使用與成員屬性同名稱的參數對成員屬性進行賦值的問題,我們可以使用 this
關鍵字:
public ImmocStudent(String nickname) {
this.nickname = nickname;
}
在方法內部,this
關鍵字是當前對象的默認引用,簡單說,誰調用了它誰就是 this
。因此,通過 this.field
就可以訪問當前實例的字段,解決實例變量和參數變量名稱沖突的問題。
如下是本小節的最終實例代碼:
public class ImoocStudent {
// 定義屬性(特征)
String nickname; // 昵稱
String position; // 職位
String city; // 城市
String sex; // 男 | 女
// 無參構造方法
public ImoocStudent() {
// 執行輸出語句
System.out.println("無參構造方法執行了...");
}
// 有參構造方法
public ImoocStudent(String nickname, String position) {
// 將參數變量賦值給實例變量
this.nickname = nickname;
this.position = position;
}
// 有參構造方法
public ImoocStudent(String nickname, String position, String city, String sex) {
this.nickname = nickname;
this.position = position;
this.city = city;
this.sex = sex;
}
// 定義方法(行為)
public void studyCourse() {
System.out.println("學習課程");
}
public void postComment() {
System.out.println("發表評論");
}
public void postArticle() {
System.out.println("發表手記");
}
public static void main(String[] args) {
// 實例化學生對象
ImoocStudent student = new ImoocStudent();
// 給成員屬性賦值
student.nickname = "Colorful";
student.position = "服務端工程師";
student.city = "北京";
student.sex = "男";
// 調用成員屬性
System.out.println("昵稱:" + student.nickname);
System.out.println("職位:" + student.position);
System.out.println("城市:" + student.city);
System.out.println("性別:" + student.sex);
ImoocStudent student1 = new ImoocStudent("慕女神", "UI設計師");
System.out.println("昵稱為:" + student1.nickname);
System.out.println("職位為:" + student1.position);
}
}
無參構造方法執行了...
昵稱:Colorful
職位:服務端工程師
城市:北京
性別:男
昵稱為:慕女神
職位為:UI設計師
6. 小結
本小節中,我們初步熟悉了 Java 中的類和對象。我們再來回顧一下本小節的重點知識:
在面向對象中,類和對象是 “模板” 和 “實例” 的關系。
類中的實例變量是每個實例獨自擁有的,它們互不干擾。
關于對象的實例化,我們是使用 new
關鍵字 + 構造方法名 () 來實現的。
當類內部我們沒有顯示定義構造方法時,系統會自動添加無參的構造方法;當在類內部顯示定義了構造方法,系統不會自動添加無參構造方法。
this
關鍵字可以解決實例變量和參數變量沖突的問題;this
關鍵字也可以調用同一類中其他的成員方法。