Java學(xué)習第八天:類與對象(二)

一、構(gòu)造方法

在Java中,構(gòu)造方法是一種特殊的方法,它的主要作用是用于創(chuàng)建對象時初始化對象。構(gòu)造方法的名稱必須與類名完全相同,并且不返回任何值,也不定義返回類型(包括void)。構(gòu)造方法可以有參數(shù),也可以沒有參數(shù)。

構(gòu)造方法的定義

1、無參構(gòu)造方法:

public class MyClass {
    public MyClass() {
        // 初始化代碼
    }
}

2、帶參構(gòu)造方法:

public class MyClass {
    private String name;
    private int age;
    
    public MyClass(String name, int age) {
        this.name = name;
        this.age = age;
    }
}
構(gòu)造方法的重載

你可以在同一個類中定義多個構(gòu)造方法,只要它們的參數(shù)列表不同(即參數(shù)的類型、數(shù)量或順序不同)。這稱為構(gòu)造方法的重載。

public class MyClass {
    private String name;
    private int age;
    
    // 無參構(gòu)造方法
    public MyClass() {
        this.name = "Unknown";
        this.age = 0;
    }
    
    // 帶一個String參數(shù)的構(gòu)造方法
    public MyClass(String name) {
        this.name = name;
        this.age = 0; // 或者其他默認值
    }
    
    // 帶兩個參數(shù)的構(gòu)造方法
    public MyClass(String name, int age) {
        this.name = name;
        this.age = age;
    }
}
調(diào)用構(gòu)造方法

當你創(chuàng)建一個類的實例時,至少會調(diào)用一個構(gòu)造方法。如果沒有明確調(diào)用其他構(gòu)造方法(通過this關(guān)鍵字),Java將自動調(diào)用無參的構(gòu)造方法。如果你在類中定義了其他構(gòu)造方法,并且想從另一個構(gòu)造方法中初始化對象的狀態(tài),可以使用this關(guān)鍵字調(diào)用其他構(gòu)造方法。例如:

public class MyClass {
    private String name;
    private int age;
    private double height; // 新增一個字段和構(gòu)造方法
    
    public MyClass() { // 無參構(gòu)造方法,可以省略,因為Java會提供一個默認的無參構(gòu)造方法,除非你定義了其他構(gòu)造方法。
        this("Unknown", 0, 0.0); // 調(diào)用帶三個參數(shù)的構(gòu)造方法
    }
    
    public MyClass(String name) { // 帶一個String參數(shù)的構(gòu)造方法,調(diào)用帶兩個參數(shù)的構(gòu)造方法并設(shè)置height為默認值。
        this(name, 0, 0.0); // 使用this調(diào)用另一個構(gòu)造方法,傳遞name和默認的age和height。
    }
    
    public MyClass(String name, int age) { // 帶兩個參數(shù)的構(gòu)造方法,調(diào)用帶三個參數(shù)的構(gòu)造方法并設(shè)置height為默認值。
        this(name, age, 0.0); // 使用this調(diào)用另一個構(gòu)造方法,傳遞name和age以及默認的height。
    }
    
    public MyClass(String name, int age, double height) { // 帶三個參數(shù)的構(gòu)造方法。
        this.name = name;
        this.age = age;
        this.height = height; // 新增字段的初始化。
    }
}

在這個例子中,this關(guān)鍵字被用來在一個構(gòu)造方法中調(diào)用另一個構(gòu)造方法,這是一種常見的做法,特別是在你想要重用初始化代碼時。注意,this調(diào)用必須是構(gòu)造方法的第一個語句。

二、封裝

在Java中,封裝(Encapsulation)是面向?qū)ο缶幊蹋∣OP)的四大基本特性之一,它指的是將對象的狀態(tài)(屬性)和行為(方法)綁定在一起,并對外隱藏對象的細節(jié),僅通過公共的接口提供訪問和操作對象的方法。這樣做的好處是可以保護對象內(nèi)部的狀態(tài),防止外部代碼直接訪問和修改,同時可以控制對數(shù)據(jù)的訪問,確保數(shù)據(jù)的安全性和完整性。

實現(xiàn)封裝的步驟

1、定義私有屬性:首先,將類的屬性定義為私有(private),這樣外部代碼就不能直接訪問這些屬性。
2、提供公共的getter和setter方法:然后,為每個私有屬性提供公共的getter(訪問器)和setter(修改器)方法。通過這些方法,你可以控制對屬性的訪問和修改,例如可以進行輸入驗證、執(zhí)行額外的邏輯等。
3、使用構(gòu)造器:構(gòu)造器用于初始化對象的狀態(tài)。通過構(gòu)造器傳遞參數(shù)給私有屬性,可以在對象創(chuàng)建時設(shè)置其初始狀態(tài)。
示例代碼

public class Person {
    // 私有屬性
    private String name;
    private int age;

    // 構(gòu)造器
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    // Getter方法
    public String getName() {
        return name;
    }

    // Setter方法
    public void setName(String name) {
        this.name = name;
    }

    // Getter方法
    public int getAge() {
        return age;
    }

    // Setter方法,這里可以添加一些邏輯,例如年齡檢查
    public void setAge(int age) {
        if (age > 0) { // 簡單的年齡驗證
            this.age = age;
        } else {
            System.out.println("年齡必須大于0");
        }
    }
}
封裝的好處
  • 提高安全性:保護對象內(nèi)部狀態(tài),防止外部代碼隨意修改。
  • 提高靈活性:可以在setter方法中添加邏輯,例如驗證輸入、執(zhí)行額外的操作等。
  • 便于維護:當類的內(nèi)部實現(xiàn)發(fā)生變化時(例如屬性名改變),只需修改類的內(nèi)部實現(xiàn)而不需要修改外部代碼。
  • 促進團隊合作:封裝使得團隊成員不必了解類的內(nèi)部實現(xiàn)細節(jié),只需通過公共接口與對象交互。

三、繼承

在Java中,繼承是一種面向?qū)ο缶幊痰臋C制,它允許我們定義一個類(稱為子類或派生類)繼承另一個類(稱為父類或基類)的屬性和方法。通過繼承,我們可以重用代碼,實現(xiàn)代碼的共享,并促進代碼的組織和模塊化。

繼承的基本語法
  • 使用extends關(guān)鍵字來實現(xiàn)繼承。
  • 子類重寫父類方法:方法名、參數(shù)列表相同
  • 權(quán)限不能更低
  • @Override 注解(推薦)
  • super 關(guān)鍵字:super.成員變量:訪問父類變量,super.成員方法():調(diào)用父類方法,super(...):調(diào)用父類構(gòu)造方法(必須第一行)
class ParentClass {
    // 父類的屬性和方法
}

class ChildClass extends ParentClass {
    // 子類的屬性和方法
}

示例
假設(shè)我們有一個Vehicle類,表示一般的交通工具,我們希望有一個Car類表示汽車,它是一種特殊的交通工具。

// 父類:Vehicle
class Vehicle {
    String color;
    int maxSpeed;

    Vehicle(String color, int maxSpeed) {
        this.color = color;
        this.maxSpeed = maxSpeed;
    }

    @Override
    void displayInfo() {
        System.out.println("Color: " + color + ", Max Speed: " + maxSpeed);
    }
}

// 子類:Car
class Car extends Vehicle {
    int numDoors;

    Car(String color, int maxSpeed, int numDoors) {
        super(color, maxSpeed); // 調(diào)用父類的構(gòu)造器
        this.numDoors = numDoors;
    }

    void displayDoors() {
        System.out.println("Number of Doors: " + numDoors);
    }
}
使用子類對象
public class TestInheritance {
    public static void main(String[] args) {
        Car myCar = new Car("Red", 200, 4); // 使用子類構(gòu)造器創(chuàng)建對象
        myCar.displayInfo(); // 調(diào)用從父類繼承的方法
        myCar.displayDoors(); // 調(diào)用子類自己的方法
    }
}
注意事項和最佳實踐

1、單一繼承:Java不支持多重繼承(即一個類繼承多個類)。但是,通過接口(Interface)可以實現(xiàn)類似多重繼承的功能。
2、訪問修飾符:子類可以訪問父類的公有(public)和受保護(protected)成員,但不能訪問私有(private)成員。如果需要訪問私有成員,可以通過公共方法(getter和setter)。
3、構(gòu)造器:子類的構(gòu)造器默認會調(diào)用父類的無參構(gòu)造器。如果父類沒有無參構(gòu)造器,則需要在子類的構(gòu)造器中顯式調(diào)用父類的其他構(gòu)造器。使用super關(guān)鍵字。
4、方法重寫:子類可以重寫父類的方法。當調(diào)用方法時,將執(zhí)行子類中重寫的方法,除非使用super關(guān)鍵字調(diào)用父類的方法。
5、多態(tài)性:通過繼承和多態(tài)性,可以在運行時決定調(diào)用哪個類的哪個方法。這是面向?qū)ο缶幊痰膹姶蠊δ苤弧?/p>

四、多態(tài)

在Java中,多態(tài)(Polymorphism)是一種允許對象在運行時表現(xiàn)出不同的形式的能力。它是面向?qū)ο缶幊蹋∣OP)中的一個核心概念,主要體現(xiàn)在以下幾個方面:

  • 父類引用指向子類對象
  • 編譯看左邊,運行看右邊
  • 向上轉(zhuǎn)型(自動):父類 引用 = new 子類();
  • 向下轉(zhuǎn)型(強制):子類 引用 = (子類) 父類引用;
  • instanceof:判斷對象真實類型
  • 多態(tài)好處:統(tǒng)一調(diào)用、擴展性強

1、方法重寫(Method Overriding)

多態(tài)主要通過方法重寫實現(xiàn)。當一個類繼承另一個類時,子類可以重寫父類中的方法,以提供特定的實現(xiàn)。這樣,當使用父類類型的引用調(diào)用被重寫的方法時,實際執(zhí)行的是子類中定義的方法。

示例代碼:

class Animal {
    void sound() {
        System.out.println("Animal makes a sound");
    }
}

class Dog extends Animal {
    @Override
    void sound() {
        System.out.println("Dog bark");
    }
}

public class TestPolymorphism {
    public static void main(String[] args) {
        Animal myAnimal = new Dog(); // 父類引用指向子類對象
        myAnimal.sound(); // 輸出: Dog bark
    }
}

2、接口實現(xiàn)(Interface Implementation)

在Java中,接口也可以實現(xiàn)多態(tài)。通過實現(xiàn)接口,不同的類可以實現(xiàn)同一接口的多個版本。

  • 完全抽象(Java 8 前)
  • 方法默認 public abstract
  • 變量默認 public static final
  • 類實現(xiàn)接口:implements
  • 一個類可以實現(xiàn)多個接口

示例代碼:

interface Animal {
    void sound();
}

class Dog implements Animal {
    public void sound() {
        System.out.println("Dog bark");
    }
}

class Cat implements Animal {
    public void sound() {
        System.out.println("Cat meow");
    }
}

public class TestPolymorphism {
    public static void main(String[] args) {
        Animal myAnimal1 = new Dog(); // 接口引用指向Dog對象
        Animal myAnimal2 = new Cat(); // 接口引用指向Cat對象
        myAnimal1.sound(); // 輸出: Dog bark
        myAnimal2.sound(); // 輸出: Cat meow
    }
}

3、抽象類(Abstract Class)與多態(tài)

抽象類也可以用來實現(xiàn)多態(tài),通過抽象類定義方法,由子類提供具體實現(xiàn)。

  • 包含 abstract 方法的類
  • 抽象方法只有聲明,沒有實現(xiàn)
  • 抽象類不能實例化
  • 子類必須重寫所有抽象方法,否則也得是抽象類

示例代碼:

abstract class Animal {
    abstract void sound(); // 抽象方法,由子類實現(xiàn)
}

class Dog extends Animal {
    void sound() {
        System.out.println("Dog bark");
    }
}

class Cat extends Animal {
    void sound() {
        System.out.println("Cat meow");
    }
}

public class TestPolymorphism {
    public static void main(String[] args) {
        Animal myAnimal1 = new Dog(); // 抽象類引用指向Dog對象
        Animal myAnimal2 = new Cat(); // 抽象類引用指向Cat對象
        myAnimal1.sound(); // 輸出: Dog bark
        myAnimal2.sound(); // 輸出: Cat meow
    }
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容