最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java面向對象基礎之封裝、繼承與多態(tài)詳細攻略

 更新時間:2026年06月03日 09:09:05   作者:寫代碼的小元  
面向對象三大特征是面向對象編程的核心,它們使得代碼更加模塊化、可重用性和可維護性更強,這篇文章主要介紹了Java面向對象基礎之封裝、繼承與多態(tài)的相關資料,文中通過代碼介紹的非常詳細,需要的朋友可以參考下

1. 前言

這篇博客主要整理 Java 面向對象基礎內(nèi)容,包括 類、方法、構造方法、方法重載、繼承和多態(tài)

相比前兩篇的基礎語法和流程控制,這一篇開始進入 Java 比較核心的部分。因為之前學過一些 C++,所以“類”“對象”“構造方法”“繼承”這些概念理解起來會有一定幫助。不過 Java 也有自己的規(guī)則,比如 Java 只支持單繼承、所有類最終都繼承自 Object,以及子類構造方法必須先調(diào)用父類構造方法等。

2. 類文件結構

一個 Java 源文件中可以定義多個類,但最多只能有一個 public 類。

如果有 public 類,那么:

public 類名必須和文件名一致。

例如文件名是 Main.java,那么其中的 public 類應該寫成:

public class Main {
}

如果要定義多個 public 類,就必須拆分到多個 .java 文件中。

3. 方法與封裝

3.1 為什么字段一般要 private?

在面向對象中,類的字段一般不直接暴露給外部,而是用 private 修飾。

例如:

class Person {
    private String name;
    private int age;
}

這樣外部代碼不能直接修改 nameage,可以避免隨便賦值導致對象狀態(tài)不合理。

字段變成 private 后,外部通過方法間接操作字段讀寫它們。

例如:

public void setAge(int age) {
    if (age < 0 || age > 100) {
        throw new IllegalArgumentException("invalid age value");
    }
    this.age = age;
}

這樣外部代碼不能直接修改 age,只能調(diào)用 setAge()。在方法內(nèi)部,我們就可以檢查參數(shù)是否合法。

再比如:

public void setName(String name) {
    if (name == null || name.isBlank()) {
        throw new IllegalArgumentException("invalid name");
    }
    this.name = name.strip();
}

這里可以避免傳入 null 或空字符串,并且用 strip() 去掉首尾空格。

簡單理解:private 字段負責隱藏數(shù)據(jù),public 方法負責提供安全的操作入口。

3.2 方法是對外接口

一個類可以通過方法給外部代碼暴露一些操作,同時自己保證內(nèi)部邏輯正確。

例如:

Person ming = new Person();
ming.setName("Xiao Ming");
ming.setAge(18);

調(diào)用方法的格式是:

實例變量.方法名(參數(shù));

4. this 關鍵字

在方法內(nèi)部,this 表示當前實例。

例如:

class Person {
    private String name;

    public String getName() {
        return this.name;
    }
}

如果沒有命名沖突,也可以省略 this

public String getName() {
    return name;
}

但是如果局部變量和字段同名,就必須使用 this。

例如:

class Person {
    private String name;

    public void setName(String name) {
        this.name = name;
    }
}

這里:

  • 前面的 this.name 表示當前對象的字段;
  • 后面的 name 表示方法參數(shù)。

如果不寫 this,就分不清了。

5. private 方法

方法也可以用 private 修飾:只能在類內(nèi)部使用,外部無法調(diào)用。

例如:

class Person {
    private int birth;

    public int getAge() {
        return calcAge(2026);
    }

    private int calcAge(int currentYear) {
        return currentYear - this.birth;
    }
}

這里 calcAge() 是一個私有方法,外部不能直接調(diào)用,但 getAge() 可以在類內(nèi)部調(diào)用它。

這個例子也說明:類對外暴露的是 getAge(),至于內(nèi)部到底有沒有 age 字段,調(diào)用者并不需要知道。

6. 可變參數(shù)

可變參數(shù)用 類型...變量名 表示。

例如:

class Group {
    private String[] names;

    public void setNames(String... names) {
        this.names = names;
    }
}

調(diào)用時可以傳入任意個參數(shù):

Group g = new Group();
g.setNames("Xiao Ming", "Xiao Hong", "Xiao Jun");
g.setNames("Xiao Ming");
g.setNames();

可變參數(shù)本質(zhì)上類似數(shù)組。

也可以寫成數(shù)組參數(shù):

public void setNames(String[] names) {
    this.names = names;
}

但這樣調(diào)用時需要手動創(chuàng)建數(shù)組:

g.setNames(new String[] {"Xiao Ming", "Xiao Hong"});

所以可變參數(shù)寫起來更方便。

可變參數(shù)可以傳入 0 個參數(shù),此時接收到的是空數(shù)組,而不是 null。

7. 參數(shù)傳遞

7.1 基本類型參數(shù)

如果參數(shù)是基本類型,傳進去的是值的副本。

例如:

public static void change(int n) {
    n = 100;
}

外部變量不會被修改。

7.2 引用類型參數(shù)

如果參數(shù)是引用類型,傳進去的是引用的副本。這個副本和外部變量指向同一個對象。

所以,如果通過這個引用修改對象內(nèi)部狀態(tài),外部也能看到變化。

但是,如果只是讓參數(shù)變量重新指向新對象,不會改變外部變量本身。

簡單記:Java 只有值傳遞。引用類型傳遞的是“引用的值”,所以可以修改對象內(nèi)部狀態(tài),但不能讓外部變量改指向。

8. 構造方法

構造方法用于創(chuàng)建對象時初始化實例。

  1. 方法名必須和類名相同;
  2. 沒有返回值,也不能寫 void
  3. 調(diào)用構造方法必須使用 new。

例如:

class Person {
    private String name;
    private int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
}

創(chuàng)建對象:

Person p = new Person("Xiao Ming", 18);

如果一個類沒有定義構造方法,編譯器會自動生成一個無參構造方法。

但是,如果我們自己定義了構造方法,編譯器就不會再自動生成默認構造方法。

例如:

class Person {
    public Person(String name) {
    }
}

這時再寫:

Person p = new Person();

就會報錯,因為無參構造方法不存在。

字段也可以直接初始化:

class Person {
    private String name = "Unnamed";
    private int age = 10;
}

構造方法也可以重載,也就是定義多個參數(shù)不同的構造方法。

9. 方法重載

方法重載指的是:方法名相同,但參數(shù)不同。

例如:

class Hello {
    public void sayHello() {
        System.out.println("Hello");
    }

    public void sayHello(String name) {
        System.out.println("Hello, " + name);
    }
}

參數(shù)不同可以是:個數(shù)、類型、順序

但一般不推薦只靠參數(shù)順序區(qū)分,容易讓人看混。

需要注意:

返回值不同不能作為方法重載的判斷依據(jù)。

例如下面這樣不算合法重載:

public int test() {
    return 1;
}

public String test() {
    return "hello";
}

因為調(diào)用 test() 時,編譯器無法只根據(jù)返回值判斷要調(diào)用哪個方法。

10. 繼承

10.1 extends 關鍵字

Java 使用 extends 實現(xiàn)繼承。

例如:

class Person {
    protected String name;
    protected int age;
}

class Student extends Person {
    private int score;
}

這里 Student 繼承自 Person。

可以理解為:

Student is a Person

通過繼承,子類可以復用父類已有的字段和方法,只需要編寫自己新增的功能。

在術語上:

  • Person 是父類、超類、基類;
  • Student 是子類、擴展類。

注意:子類不要定義和父類重名的字段,否則容易造成混亂。

10.2 Object 類

在 Java 中,如果一個類沒有顯式寫 extends,編譯器會自動讓它繼承 Object。

也就是說:

class Person {
}

實際上可以理解為:

class Person extends Object {
}

所以,所有 Java 類最終都繼承自 Object

繼承關系可以簡單理解為:

Object
  ↑
Person
  ↑
Student

Java 只允許一個類繼承一個父類,也就是單繼承。

11. protected 關鍵字

protected 可以讓字段或方法在繼承樹內(nèi)部訪問。

例如:

class Person {
    protected String name;
}

子類可以訪問:

class Student extends Person {
    public String hello() {
        return "Hello, " + name;
    }
}

訪問權限大致可以簡單記成:

private     只能本類訪問
protected   本類和子類可以訪問
public      外部都可以訪問

12. super 關鍵字

super 表示父類。

在子類中,可以用 super 調(diào)用父類構造方法或父類方法。

12.1 子類構造方法必須先調(diào)用父類構造方法

例如:

class Person {
    protected String name;
    protected int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
}

如果子類這樣寫:

class Student extends Person {
    protected int score;

    public Student(String name, int age, int score) {
        this.score = score;
    }
}

會報錯。

原因是:Java 要求子類構造方法的第一行必須先調(diào)用父類構造方法。

如果沒有寫,編譯器會自動加上:

super();

但父類 Person 沒有無參構造方法,所以會報錯。

正確寫法是:

class Student extends Person {
    protected int score;

    public Student(String name, int age, int score) {
        super(name, age);
        this.score = score;
    }
}

如果父類沒有無參構造方法,子類必須顯式調(diào)用 super(...)。

12.2 子類不會繼承父類構造方法

這一點也容易忘:

子類不會繼承父類的構造方法。

子類要創(chuàng)建對象,必須有自己的構造方法。如果沒寫,編譯器可以生成默認構造方法,但它不是從父類繼承來的。

13. 向上轉型和向下轉型

13.1 向上轉型

把子類類型賦值給父類類型,叫向上轉型。

例如:

Student s = new Student();
Person p = s;
Object o = s;

這是安全的,因為 Student is a Person,同時也是 Object。

13.2 向下轉型

把父類類型強制轉成子類類型,叫向下轉型。

例如:

Person p1 = new Student();
Student s1 = (Student) p1;

這是可以的,因為 p1 實際指向的是 Student 對象。

但是:

Person p2 = new Person();
Student s2 = (Student) p2;

會在運行時報錯,因為 p2 實際上不是 Student。

向下轉型可能失敗,失敗時會拋出 ClassCastException。

13.3 instanceof

為了避免向下轉型出錯,可以先用 instanceof 判斷。

Person p = new Student();

if (p instanceof Student) {
    Student s = (Student) p;
}

instanceof 用來判斷一個引用變量指向的對象是不是某個類型,或者這個類型的子類。

如果變量是 null,那么 instanceof 的結果一定是 false。

較新的 Java 版本中,還可以寫成:

Object obj = "hello";

if (obj instanceof String s) {
    System.out.println(s.toUpperCase());
}

這樣判斷成功后,可以直接使用變量 s

14. 繼承和組合

繼承表示 is-a 關系。

例如:

Student is a Person

組合表示 has-a 關系。

例如:

Car has an Engine

如果只是“擁有某個對象”,不應該強行使用繼承。

簡單記:is-a 用繼承,has-a 用組合。

實際開發(fā)中,很多時候會優(yōu)先考慮組合,因為繼承會讓子類和父類綁定得更緊,而且 Java 只支持單繼承。

15. 多態(tài)

15.1 Override 和 Overload 的區(qū)別

Override 是覆寫,發(fā)生在父類和子類之間。

如果子類定義了一個和父類方法簽名相同的方法,就是覆寫。

例如:

class Person {
    public void run() {
        System.out.println("Person run");
    }
}

class Student extends Person {
    @Override
    public void run() {
        System.out.println("Student run");
    }
}

Overload 是重載,發(fā)生在同一個類中,方法名相同,但參數(shù)不同。

例如:

public void hello() {
}

public void hello(String name) {
}

兩者區(qū)別:

概念含義
Overload方法名相同,參數(shù)不同,是新方法
Override方法簽名相同,子類覆蓋父類方法

建議覆寫方法時加上 @Override

這樣如果方法簽名寫錯,編譯器會提醒。

例如:

class Person {
    public void run() {
    }
}

class Student extends Person {
    @Override
    public void run(String s) {
    }
}

這里會編譯報錯,因為 run(String s) 并沒有覆寫父類的 run()。

15.2 動態(tài)方法調(diào)用

多態(tài)最重要的一點是:

Java 的實例方法調(diào)用,取決于對象的實際類型,而不是變量的聲明類型。

例如:

Person p = new Student();
p.run();

雖然變量 p 的聲明類型是 Person,但它實際指向的是 Student 對象。

如果 Student 覆寫了 run(),那么最終調(diào)用的是 Studentrun()。

這就是多態(tài)。

多態(tài)的好處是:代碼可以面向父類編寫,運行時根據(jù)實際子類對象調(diào)用不同實現(xiàn)。

15.3 覆寫 Object 的方法

所有類最終都繼承自 Object,所以可以根據(jù)需要覆寫 Object 中的一些方法。

常見方法有:

方法作用
toString()把對象轉換成字符串
equals()判斷對象是否邏輯相等
hashCode()返回對象的哈希值

例如:

class Person {
    private String name;

    @Override
    public String toString() {
        return "Person: name=" + name;
    }

    @Override
    public boolean equals(Object o) {
        if (o instanceof Person p) {
            return this.name.equals(p.name);
        }
        return false;
    }

    @Override
    public int hashCode() {
        return this.name.hashCode();
    }
}

初學階段先知道:如果希望對象打印得更清楚,可以覆寫 toString();如果希望按內(nèi)容比較對象,可以覆寫 equals()。

16. final 關鍵字

final 可以修飾類、方法和字段。

16.1 final 類

如果一個類用 final 修飾,那么它不能被繼承。

例如:

public final class String {
}

String 類就是 final 的,所以不能被繼承。

16.2 final 方法

如果一個方法用 final 修飾,那么它不能被子類覆寫。

class Person {
    public final void run() {
    }
}

16.3 final 字段

如果字段用 final 修飾,那么初始化后不能再重新賦值。

class Person {
    public final String name;

    public Person(String name) {
        this.name = name;
    }
}

這有點像 C++ 里的 const,可以保證字段初始化后不再改變。

需要注意:如果 final 修飾的是引用類型,那么這個引用不能再指向別的對象,但對象內(nèi)部狀態(tài)是否能變,要看這個對象本身是否可變。

17. 今日易錯點總結

17.1private字段不是不能用,而是要通過方法間接使用

字段設成 private 后,外部不能直接訪問,但可以通過 get、set 方法間接訪問。

這樣做的好處是可以在方法里檢查參數(shù),保證對象狀態(tài)合理。

17.2this主要用來區(qū)分字段和局部變量

如果字段和參數(shù)同名,必須寫:

this.name = name;

否則容易把局部變量和字段混在一起。

17.3 返回值不同不能構成重載

重載看的是參數(shù)列表,不看返回值。

17.4 子類構造方法必須先調(diào)用父類構造方法

如果父類沒有無參構造方法,子類必須顯式寫:

super(...);

并且它必須是構造方法中的第一條語句。

17.5 向下轉型前最好先用 instanceof 判斷

向上轉型一定安全,向下轉型可能失敗。

為了避免 ClassCastException,可以先判斷:

if (p instanceof Student) {
    Student s = (Student) p;
}

17.6 Override 和 Overload 不要混

  • Overload:方法名相同,參數(shù)不同;
  • Override:子類覆寫父類方法,方法簽名相同。

覆寫時建議加上 @Override,讓編譯器幫忙檢查。

18. 學習小結

今天感覺最不好理解的是 多態(tài)。尤其是 Person p = new Student(); 這種寫法,變量的聲明類型和對象的實際類型不一樣,最后調(diào)用方法時又是根據(jù)實際類型來決定,這個地方剛開始看會有點繞。現(xiàn)在可以先簡單理解為:父類變量可以指向子類對象,而真正執(zhí)行哪個方法,要看運行時對象到底是誰。

不過 getName()、setName() 這一類方法就比較好理解,也能明顯感覺到它們的作用。字段設成 private 后,外部不能隨便修改數(shù)據(jù),只能通過方法間接訪問。這樣就可以在 setAge()、setName() 里做參數(shù)檢查,避免把年齡設置成負數(shù),或者把名字設置成空字符串。相比直接暴露字段,這種寫法對數(shù)據(jù)有更好的保護性,是很值得學習的寫法。

目前感覺,面向對象的重點不是只記住某個語法形式,而是理解“類如何對外提供接口、如何隱藏內(nèi)部細節(jié)、子類和父類之間到底是什么關系”。這些關系理清楚之后,后面再學接口、抽象類和更復雜的多態(tài)應該會更容易一些。

第三篇 Java 學習博客就先記錄到這里~

19. 參考資料

到此這篇關于Java面向對象基礎之封裝、繼承與多態(tài)的文章就介紹到這了,更多相關Java封裝、繼承與多態(tài)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • Java流程控制語句最全匯總(中篇)

    Java流程控制語句最全匯總(中篇)

    這篇文章主要介紹了Java流程控制語句最全匯總(中篇),本文章內(nèi)容詳細,通過案例可以更好的理解數(shù)組的相關知識,本模塊分為了三部分,本次為中篇,需要的朋友可以參考下
    2023-01-01
  • Nacos+Spring Cloud Gateway動態(tài)路由配置實現(xiàn)步驟

    Nacos+Spring Cloud Gateway動態(tài)路由配置實現(xiàn)步驟

    Nacos最近項目一直在使用,本文通過gateway、nacos-consumer、nacos-provider三個簡單模塊來展示:Nacos下動態(tài)路由配置,,感興趣的小伙伴們可以參考一下
    2021-08-08
  • 學會在Java中使用Optional功能

    學會在Java中使用Optional功能

    這篇文章主要介紹了學會在Java中使用Optional功能,在本文中,我們將了解如何、何時以及在哪里最好地應用Optional,具體相關內(nèi)容需要的朋友可以參考下面文章內(nèi)容
    2022-09-09
  • 使用 Java8 實現(xiàn)觀察者模式的方法(下)

    使用 Java8 實現(xiàn)觀察者模式的方法(下)

    這篇文章主要介紹了使用 Java8 實現(xiàn)觀察者模式的方法(下)的相關資料,需要的朋友可以參考下
    2016-02-02
  • SpringCloud之Config配置中心與Redis分布式鎖詳解

    SpringCloud之Config配置中心與Redis分布式鎖詳解

    這篇文章主要給大家介紹了SpringCloud Alibaba中Config配置中心,Redis分布式鎖,文中有詳細的代碼示例供大家參考,需要的朋友可以參考閱讀
    2023-05-05
  • 解析java中的condition

    解析java中的condition

    Condition 將 Object 監(jiān)視器方法(wait()、notify()和notifyAll())分解成截然不同的對象,以便通過將這些對象與任意Lock實現(xiàn)組合使用,為每個對象提供多個等待 set(wait-set)
    2021-06-06
  • 在本地用idea連接虛擬機上的hbase集群的實現(xiàn)代碼

    在本地用idea連接虛擬機上的hbase集群的實現(xiàn)代碼

    這篇文章主要介紹了在本地用idea連接虛擬機上的hbase集群的實現(xiàn)代碼,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-10-10
  • 使用java編程從0到1實現(xiàn)一個簡單計算器

    使用java編程從0到1實現(xiàn)一個簡單計算器

    這篇文章主要介紹了使用java編程從0到1實現(xiàn)一個簡單計算器,文章中用代碼實例講解的很清晰,有感興趣的同學可以學習研究下
    2021-02-02
  • SpringCloud Config使用配置方法

    SpringCloud Config使用配置方法

    這篇文章給大家介紹SpringCloud Config使用及構建配置中心的方法,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友參考下吧
    2021-07-07
  • 帶你快速搞定java IO

    帶你快速搞定java IO

    這篇文章主要介紹了Java IO流 文件傳輸基礎的相關資料,非常不錯,具有參考借鑒價值,需要的朋友可以參考下,希望能給你帶來幫助
    2021-07-07

最新評論

黎城县| 荆门市| 聂拉木县| 大新县| 永登县| 伽师县| 大关县| 常山县| 新余市| 黑河市| 杭锦旗| 资溪县| 若尔盖县| 崇阳县| 天全县| 星座| 漳浦县| 文山县| 镇巴县| 镇安县| 巍山| 棋牌| 教育| 策勒县| 延庆县| 乌兰浩特市| 利辛县| 封开县| 石狮市| 大洼县| 荔波县| 乃东县| 隆昌县| 浦东新区| 昌黎县| 色达县| 当阳市| 克什克腾旗| 资溪县| 开平市| 潼关县|