- 面向物件和面向程序的區別
- 面向物件概念
- 類和類的實體化
- 類的成員
- 認識null
- static 關鍵字
- 封裝
- private實作封裝
- getter和setter方法
- 構造方法
- this關鍵字
- 代碼塊
- 總結
面向物件和面向程序的區別
眾所周知,Java是種面向物件編程,在學習類和物件時,我們先來了解一下什么是面向物件編程,
面向程序(如:C語言)
面向程序的語言也稱為結構化程式設計語言,是高級語言的一種,在面向程序程式設計中,問題被看作一系列需要完成的任務,函式則用于完成這些任務,解決問題的焦點集中于函式,其概念最早由E.W.Dijikstra在1965年提出,是軟體發展的一個重要里程碑,它的主要觀點是采用自頂向下、逐步求精的程式設計方法,使用三種基本控制結構構造程式,即任何程式都可由順序、選擇、回圈三種基本控制結構構造
面向物件(如:Java、C++)
面向物件程式設計(Object Oriented Programming)作為一種新方法,其本質是以建立模型體現出來的抽象思維程序和面向物件的方法,模型是用來反映現實世界中事物特征的,任何一個模型都不可能反映客觀事物的一切具體特征,只能對事物特征和變化規律的一種抽象,且在它所涉及的范圍內更普遍、更集中、更深刻地描述客體的特征,通過建立模型而達到的抽象是人們對客體認識的深化,
簡單來說,面向程序注重的是程序,在整個程序中所涉及的行為,就是功能,
面向物件注重的是物件,也就是參與程序所涉及到的主體,是通過邏輯將一個個功能實作連接起來
舉個例子
- 面向程序: 1.把冰箱打開 2. 把大象放入 3. 冰箱關起來
- 面向物件: 打開冰箱,儲存,關閉都是對冰箱的操作,是冰箱的行為,冰箱就是一個物件,所以只要操作冰箱所具備的功能,都要定義在冰箱中
面向物件概念
- 面向物件是思考問題的一種思考方式,是一種思想,比如:概念與實體,理論與實踐,名和實等等,
- 類就是一類物件的統稱,物件就是這一類具體化的一個實體,
- 面向物件的好處:將復雜的事情變簡單了,只要面對一個物件就行,
簡而言之
面向物件就是用代碼(類)來描述客觀世界的事物的一種方式. 一個類主要包含一個事物的屬性和行為,
類和類的實體化
- 類就是一類物件的統稱,物件就是這一類具體化的一個實體,
基本語法
// 創建類
class <class_name>{
field;//成員屬性
method;//成員方法
}
// 實體化物件
<class_name> <物件名> = new <class_name>();
-
class為定義類的關鍵字,ClassName為類的名字,{ } 中為類的主體,
-
類中的元素稱為:成員屬性,類中的函式稱為:成員方法,
類的創建
宣告一個類就是創建一個新的資料型別,而類在 Java 中屬于參考型別, Java 使用關鍵字 class 來宣告類,我們來看以下簡單的宣告一個類
示例
class Person { //使用class創建一個Person類
public int age;//成員屬性
public String name;// 成員屬性
public String sex;//成員屬性
public void eat() { //成員方法
System.out.println("吃飯!");
}
public void sleep() { //成員方法
System.out.println("睡覺!");
}
}
我們這里這是創建了一個類,并沒有把這個類實體化,類就像是設計圖,只設計出需要什么東西,但是并沒有物體的建筑存在,同樣類也只是一個設計,實體化出的物件才能實際存盤資料,占用物理空間,
- 類只是一個模型一樣的東西,限定了類有哪些成員.
- 一個類可以實體化出多個物件,實體化出的物件 占用實際的物理空間,存盤類成員變數

那么怎么將類實體化呢?
這時候我們就要通過另一個關鍵字new來將類實體化,用型別別創建物件的程序,稱為類的實體化,
類的實體化
- new 關鍵字用于創建一個物件的實體.
- 使用 . 來訪問物件中的屬性和方法.
- 同一個類可以創建對個實體.
示例
//結合上文代碼觀看
public class Main{
public static void main(String[] args) {
Person person = new Person();//通過new實體化物件
person.eat();//成員方法呼叫需要通過物件的參考呼叫
person.sleep();
//產生物件 實體化物件
Person person2 = new Person();
Person person3 = new Person();
}
}
通過new關鍵字創建的實體化我們稱為實體化物件,而用型別別創建的變數我們稱之為物件的參考,通過物件參考可以找到實體化物件,我們可以通過 物件參考.成員變數/成員方法 來呼叫類里面創建的變數及方法,
運行示例

關于記憶體布局,物件的參考是放在記憶體中的堆疊區,而實體化物件是放在記憶體中的堆區,
來看一張圖

從圖中可以看到,物件的參考是在堆疊上開辟的,而參考指向的實體化物件的空間是在對上開辟的,每次使用new實體化一個物件時,都會在堆上開辟一塊空間,每個實體化物件都包含類中的成員屬性,
類的成員
- 類的成員可以包含以下:欄位、方法、代碼塊、內部類和介面等,
這里我就暫時先介紹前三個,
欄位/屬性/成員變數
在類中, 方法外部定義的變數. 這樣的變數我們稱為 “欄位” 或 “屬性” 或 “成員變數”(三種稱呼都可以, 一般不會嚴格區分),用于描述一個類中包含哪些資料.
class Person {
public String name; // 欄位 成員變數 屬性
public int age;
}
- 使用 . 訪問物件的欄位.
- “訪問” 既包含讀, 也包含寫.
- 對于一個物件的欄位如果沒有顯式設定初始值, 那么會被設定一個默認的初值
默認值可以參考以下這幅圖

成員方法
成員方法其實就是類里面的創建的方法,稱之為成員方法,用于描述一個物件的行為,其訪問方式跟成員變數一樣,這里過一遍應該就能懂,
class Person {
public int age = 18;//成員變數
public String name = "張三"; //成員變數
public void show() { //成員方法
System.out.println("我叫" + name + ", 今年" + age + "歲");
}
}
認識null
- null 在 Java 中為 “空參考”, 表示不參考任何物件. 類似于 C 語言中的空指標. 如果對 null 進行 . 操作就會引發例外.
代碼示例
class Person{
public int age;
public String name;
}
public class Test {
public static void main(String[] args) {
Person person = null;//person指向空
System.out.println(person.age);//對null進行.操作
}
}
運行結果
報錯空指標例外

如果以后寫代碼出現這種報錯那就是因為你的參考指向了null,
static 關鍵字
static的作用
- 修飾屬性
- 修飾方法
- 代碼塊
- 修飾類(暫時不做介紹)
static修飾屬性
Java靜態屬性和類相關, 和具體的實體無關. 換句話說, 同一個類的不同實體共用同一個靜態屬性.
class TestDemo{
public int a;
public static int count;//static修飾的成員變數,簡稱靜態成員變數
}
public class Main{
public static void main(String[] args) {
TestDemo t1 = new TestDemo();
t1.a++;
t1.count++;
System.out.println(t1.a);
System.out.println(t1.count);//通過類名.靜態成員變數訪問
System.out.println("============");
TestDemo t2 = new TestDemo();
t2.a++;
t2.count++;
System.out.println(t2.a);
System.out.println(t2.count);
}
}
運行結果
運行結果決議:被static修飾的成員變數被兩個不同的參考改變了值,這是因為被static所修飾的屬性是被所有類所屬,切不屬于物件,在記憶體布局當中被static修飾的屬性是放在記憶體中的方法區,被修飾的屬性在記憶體中只有一份,所有在兩個不同的參考訪問時其實就是訪問相同的一個記憶體并改變了其屬性的值,
上列代碼中通過參考訪問靜態屬性其實是不規范的,正確訪問應該是類名.靜態屬性
//正確訪問
TestDemo.count++;
修飾方法
- 如果在任何方法上應用 static 關鍵字,此方法稱為靜態方法,
靜態方法屬于類,而不屬于類的物件, - 可以直接呼叫靜態方法,而無需創建類的實體,
- 靜態方法可以訪問靜態資料成員,并可以更改靜態資料成員的值,
- 靜態方法不可訪問非靜態資料成員
class TestDemo{
public int a;
public static int count;
public static void change() {
count = 100;
//a = 10; error 不可以訪問非靜態資料成員,否則會出現例外
}
}
public static void main(String[] args) {
TestDemo.change();//無需創建實體物件 就可以呼叫
System.out.println(TestDemo.count);
}
運行結果

注意事項 靜態方法和實體無關, 而是和類相關. 因此這導致了兩個情況
- 靜態方法不能直接使用非靜態資料成員或呼叫非靜態方法(非靜態資料成員和方法都是和實體相關的).
- this和super兩個關鍵字不能在靜態背景關系中使用(this 是當前實體的參考, super是當前實體父類實體的參考, 也是和當前實體相關)
擴展
static是不能修飾區域變數的,如果使用static修飾區域變數,就會發生報錯,

這是因為,每次你呼叫成員方法時,它都會創建一個區域的靜態變數,而static修飾的屬性生命周期是隨著類的生命周期結束而結束的,比區域變數的生命周期更長,而被static修飾的屬性,在記憶體中只會存在一份,如果修飾了區域變數,每次呼叫創建一個每次呼叫創建一個,前面又說了只存在一份,這就會很矛盾,故不能使用static修飾區域變數
封裝
什么是封裝?
-
軟體開發的本質就是對程式復雜程度的管理. 如果一個軟體代碼復雜程度太高, 那么就無法繼續維護. 如何管理復雜程度? 封裝就是最基本的方法.
-
在我們寫代碼的時候經常會涉及兩種角色: 類的實作者和類的呼叫者.
-
封裝的本質就是讓類的呼叫者不必太多的了解類的實作者是如何實作類的, 只要知道如何使用類就行了.這樣就降低了類使用者的學習和使用成本, 從而降低了復雜程度
private實作封裝
private/ public 這兩個關鍵字表示 “訪問權限控制” .
- 被 public(公共類)修飾的成員變數或者成員方法, 可以直接被類的呼叫者使用.
- 被 private(私有類) 修飾的成員變數或者成員方法, 不能被類的呼叫者使用.(只能在本類使用)
換句話說, 類的使用者根本不需要知道, 也不需要關注一個類都有哪些 private 的成員. 從而讓類呼叫者以更低的成本來使用類.
范例:使用 private 封裝屬性, 并提供 public 方法供類的呼叫者使用
class Person {
private String name = "張三";
private int age = 18;
public void show() {
System.out.println("我叫" + name + ", 今年" + age + "歲");
}
}
public static void main(String[] args) {
Person person = new Person();
person.show();
}
此時欄位已經使用 private 來修飾. 類的呼叫者(main方法中)不能直接使用. 而需要借助 show 方法. 此時類的使用者就不必了解 Person 類的實作細節.
同時如果類的實作者修改了欄位的名字, 類的呼叫者不需要做出任何修改(類的呼叫者根本訪問不到 name, age這樣的欄位).
getter和setter方法
當欄位被private修飾后,我們在主方法中是無法直接訪問該欄位的,此時如果需要獲取或者修改這個 private 屬性, 就需要使用 getter / setter 方法.
getter方法
getName 即為 getter 方法, 表示獲取這個成員的值.
class Person {
private String name = "張三";
private int age = 18;
public void show() {
System.out.println("我叫" + name + ", 今年" + age + "歲");
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
}
public static void main(String[] args) {
Person person = new Person();
int age = person.getAge();
System.out.println(age);
}
設定了getter方法后,這時我們就可以在main方法中獲取被private修飾的欄位的值,
運行結果

setter方法
setName 即為 setter 方法, 表示設定這個成員的值
class Person {
private String name = "張三";
private int age = 18;
public void show() {
System.out.println("我叫" + name + ", 今年" + age + "歲");
}
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
}
public static void main(String[] args) {
Person person = new Person();
int age = person.getAge();
System.out.println(age);
}
設定了setter方法后,這時我們就可以在main方法中設定被private修飾的欄位的值,
運行結果

注意事項
- 當set方法的形參名字和類中的成員屬性的名字一樣的時候,如果不使用this, 相當于自賦值. this 表示當前實體的參考.
- 不是所有的欄位都一定要提供 setter / getter 方法, 而是要根據實際情況決定提供哪種方法.
- 在 IDEA 中可以使用 alt + insert (或者 alt + F12) 快速生成 setter / getter 方法. 在 VSCode 中可以使用滑鼠右鍵選單 -> 源代碼操作 中自動生成 setter / getter 方法.
第一點我待會會在下文中講到,關于第三點,如果使用的IDEA快捷鍵無法打開時,可以在空白處右擊滑鼠,然后跟著下圖操作即可自動生成

構造方法
構造方法是一種特殊方法, 使用關鍵字new實體化新物件時會被自動呼叫, 用于完成初始化操作.
語法規則
- 方法名稱必須與類名稱相同
- 構造方法沒有回傳值型別宣告
- 每一個類中一定至少存在一個構造方法(沒有明確定義,則系統自動生成一個無參構造)
先看一段代碼
class Person {
private String name;//實體成員變數
private int age;
private String sex;
//不帶引數的構造引數
public Person() {
name = "caocao";
age = 10;
sex = "男";
System.out.println("呼叫了不帶引數的構造方法");
}
//帶引數的構造方法
public Person(int a){
name = "hello";
age = a;
sex = "女";
System.out.println("呼叫了帶引數的構造方法");
}
}
public static void main(String[] args) {
Person person = new Person();
Person person2 = new Person(20);
}
運行結果

通過運行結果我們看到,呼叫構造方法是在實體化一個物件的時候執行的,Java會根據你是否給了引數來呼叫對應的構造方法,如果沒有寫構造方法,則系統會自動生成一個無參的構造方法,需要注意的是,如果自己寫了構造方法,則系統將不會自動生成無參的構造方法,
看到這里的讀者不知道考沒考慮過一個問題,如果在類中創建的方法(普通方法,靜態方法,構造方法等)里面的引數名和類中創建的成員名一樣會怎么樣,來看一段代碼(這里拿構造方法舉例)
class Person {
public String name;//實體成員變數
public int age;
public String sex;
public Person(String name,int age,String sex){
name = name;
age = age;
sex = sex;
}
}
public static void main(String[] args) {
Person person = new Person("張三",18,"男");
System.out.println(person.name);
System.out.println(person.age);
System.out.println(person.sex);
}
運行結果

我們發現輸出的都是對應型別的默認值,并沒有改變對應的欄位,這是因為,當區域變數名與成員屬性名相同時區域會優先,所以在上列代碼中相當于區域變數自己給自己賦值了,遇到這種情況我們就要使用this關鍵字來區分成員變數和區域變數,
this關鍵字
- this表示當前物件參考(注意不是當前物件). 可以借助 this 來訪問物件的欄位和方法
我們可以將上面代碼改動一下,把所有的成員變數加上this關鍵字
public Person(String name,int age,String sex){
this.name = name;
this.age = age;
this.sex = sex;
}
這時候代碼就能成功輸出了

this的三種用法
- this.成員變數名:呼叫當前物件的屬性
- this.方法名:呼叫當前物件的方法
- this():呼叫自己的構造方法
前兩點使用方法都是一樣的,可以參考上面改動代碼,關于第三點需要注意:只能在構造方法里使用,只能呼叫一個構造方法,只能放在構造方法的第一行,
還需要注意的是this關鍵字是不能訪問靜態方法和靜態變數的,靜態方法里面也不能使用this,
代碼塊
這個知識點很簡單,相信過一遍就能清楚了
什么是代碼塊?
使用 {} 定義的一段代碼,根據代碼塊定義的位置以及關鍵字,又可分為以下四種:
- 普通代碼塊
- 構造代碼塊
- 靜態代碼塊
- 同步代碼塊
這里我就先介紹前面三種代碼塊
普通代碼塊
就是定義在方法的代碼塊叫做普通代碼塊
public static void main(String[] args) {
//直接用{}定義普通代碼塊
{
System.out.println("普通代碼塊");
}
}
用法比較少見,沒多大用處,哈哈,
構造代碼塊
定義在類中的代碼塊(不加修飾符),也叫:實體代碼塊,
class Person {
public String name;//實體成員變數
public int age;
public String sex;
//構造(實體)代碼塊
{
this.name = "張三";
this.age = 18;
this.sex = "男";
}
}
構造代碼塊一般用于初始化實體成員變數,
靜態代碼塊
使用static定義的代碼塊,
class Person {
public String name;//實體成員變數
public int age;
public String sex;
static public int count;
//靜態代碼塊
static {
count = 10;
}
}
一般用于初始化靜態成員屬性,
其實代碼塊也有執行順序的,來看一段代碼
class Person {
public Person(){
System.out.println("構造方法");
}
//構造(實體)代碼塊
{
System.out.println("構造代碼塊");
}
//靜態代碼塊
static {
System.out.println("靜態代碼塊");
}
}
public static void main(String[] args) {
Person person1 = new Person();
System.out.println("--------------分割線------------");
Person person2 = new Person();
}
運行結果

通過運行結果可以看到,不管你代碼塊位置在上面還是下面,執行順序都是靜態代碼塊->構造代碼塊->構造方法,且靜態代碼塊只會執行一次,
總結
- 一個類可以產生無數的物件,類就是模板,物件就是具體的實體,
- 類中定義的屬性,大概分為幾類:類屬性,物件屬性,其中被static所修飾的資料屬性稱為類屬性, static修飾的方法稱為類方法,特點是不依賴于物件,我們只需要通過類名就可以呼叫其屬性或者方法,
- 靜態代碼塊優先實體代碼塊執行,實體代碼塊優先建構式執行,
- this關鍵字代表的是當前物件的參考,并不是當前物件,
這里就是本文講的所有內容,有錯誤的地方歡迎大家指出,寫博客也是為了記錄自己的學習程序,希望能給讀者帶來幫助,
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/279982.html
標籤:java
上一篇:Java類和物件(重點詳解)
