首頁 > 軟體

一文詳解Object類和抽象類

2022-08-23 18:01:16

一、抽象類是什麼?

在物件導向的概念中,所有的物件都是通過類來描繪的,但是反過來,並不是所有的類都是用來描繪物件的,如果一個類中沒有包含足夠的資訊來描繪一個具體的物件,這樣的類就是抽象類

由於抽象類不能範例化物件,所以抽象類必須被繼承,才能被使用。也是因為這個原因,通常在設計階段決定要不要設計抽象類。
父類別包含了子類集合的常見的方法,但是由於父類別本身是抽象的,所以不能使用這些方法。

二、初始抽象類

2.1 基本語法

在 Java 語言中使用 abstract class 來定義抽象類。

如下範例:

abstract class Employee {

    //普通的成員屬性
    private String name;
    private String address;

    //構造方法
    public Employee(String name, String address) {
        this.name = name;
        this.address = address;
    }

    //普通的成員方法
    public String getName() {
        return name;
    }

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

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }
}

注意到該 Employee 類沒有什麼不同,儘管該類是抽象類,但是它仍然有 成員變數,成員方法和 構造方法

注意:抽象類也是類,內部可以包含普通方法和屬性,甚至構造方法

public static void main(String[] args) {
        Employee employee = new Employee("zhangsan","shanxi");
    }

程式碼可以編譯通過嗎?

我們可以發現抽象類是無法範例化物件的.

2.2 繼承抽象類

1.抽象方法的許可權

abstract class Shape {
    abstract private void func();
}

抽象類要被繼承,需要子類實現抽象方法,所以抽象方法的許可權不能是private.

注意:抽象方法沒有加存取限定符時,預設是public.

abstract class Shape {
    abstract final void func();
}

** 抽象方法不能被final和static修飾,因為抽象方法要被子類重寫**

先寫一個Shape抽象類:

abstract class Shape {
    //被abstract修飾的抽象方法,沒有方法體
    abstract public void draw();
    abstract void calcArea();
}

抽象類必須被繼承,並且繼承後子類要重寫父類別中的抽象方法,否則子類也是抽象類,必須要使用 abstract 修飾

class Circle extends Shape {
    private double r;
    final private static double PI = 3.14;

    public Circle(double r) {
        this.r = r;
    }

    @Override
    public void draw() {
        System.out.println("畫圓!");
    }

    @Override
    void calcArea() {
        System.out.println("面積為: "+PI*r*r);
    }
}
public static void main(String[] args) {
        Circle circle = new Circle(2);
        circle.draw();
        circle.calcArea();
    }

實現父類別的抽象方法後,即可正常範例化

class Rect extends Shape {
    @Override
    public void draw() {
        
    }
}

子類繼承抽象類時,要麼把抽象方法全部實現,不然將子類繼續抽象化.

三、抽象類總結

  • 1.抽象類中必須使用abstract修飾類
  • 2.抽象類中可以包含普通類所能包含的成員
  • 3.抽象類和普通類不一樣的是:抽象類可以包含抽象方法.
  • 4.抽象方法使用abstract修飾的,這個方法沒有具體的實現
  • 5.不能範例化抽象類
  • 6.抽象類最大的意義就是被繼承
  • 7.如果一個普通類繼承了一個抽象類,那麼必須重寫抽象類當中的方法,否則寫為抽象類
  • 8.抽象方法不能是私有的,static?也就是要滿足重寫的規則
  • 9.final?不可以它和abstract是矛盾的
  • 10.抽象類當中可以有構造方法,為了方便子類呼叫,來初始化類中的成員變數.
  • 11.抽象類的出現,是為了讓程式設計師更早的發現錯誤,防止出錯,讓編譯器及時提醒我們.

四、Object類

4.1 初始Object

Java Object 類是所有類的父類別,也就是說 Java 的所有類都繼承了 Object,子類可以使用 Object 的所有方法。
Object 類位於 java.lang 包中,編譯時會自動匯入,我們建立一個類時,如果沒有明確繼承一個父類別,那麼它就會自動繼承 Object,成為 Object 的子類。

class Person {
    
}
class Person extends Object {
    
}

這兩種是一模一樣的.

4.2 toString

Object中的toString方法:

public static void main(String[] args) {
        Circle circle = new Circle(2);
        System.out.println(circle);
    }

我們要列印circle物件具體內容的話,需要重寫toString方法.

public String toString() {
        return "Circle{" +
                "r=" + r +
                '}';
    }

4.3 equals

在Java中,進行比較時:

  • a.如果雙等號左右兩側是基本型別變數,比較的是變數中值是否相同
  • b.如果雙等號左右兩側是參照型別變數,比較的是參照變數地址是否相同
  • c.如果要比較物件中內容,必須重寫Object中的equals方法,因為equals方法預設也是按照地址比較的:
public static void main(String[] args) {
        Circle circle = new Circle(2);
        Circle circle1 = new Circle(2);
        int a = 1;
        int b = 1;
        System.out.println(a == b);
        System.out.println(circle == circle1);
        System.out.println(circle.equals(circle1));
    }

每次new一個物件都會在堆開闢一個新的空間.

Object定義的equals方法,在兩個物件呼叫時對比的是兩個物件地址是否相等,而不是具體物件中的內容這時候我們需要重寫equals方法.

 @Override
    public boolean equals(Object obj) {
        if(obj == null) {
            return false;
        }
        if(this == obj) {
            return true;
        }
        if(!(obj instanceof Circle)) {
            return false;
        }
        Circle circle = (Circle)obj;
        return this.r == circle.r;
    }

比較物件中內容是否相同的時候,一定要重寫equals方法。

4.4 hashcode

我們可以發現toString方法中有使用到這個方法,我們目前只需要知道它是一個記憶體地址,然後呼叫Integer.toHexString()方法,將這個地址以16進位制輸出。

public static void main(String[] args) {
        Circle circle1 = new Circle(2);
        Circle circle2 = new Circle(2);
        System.out.println(circle1.hashCode());
        System.out.println(circle2.hashCode());
    }

我們認為兩個儲存相同值的Circle物件,在呼叫Object的hashcode方法時,輸出的值不一樣.

//重寫hashCode方法
@Override
    public int hashCode() {
        return Objects.hash(r);
    }

當我們重寫hashCode後,當兩個物件儲存的內容一樣時,輸出的雜湊值是一樣的.

結論:

  • 1、hashcode方法用來確定物件在記憶體中儲存的位置是否相同
  • 2、事實上hashCode() 在雜湊表中才有用,在其它情況下沒用。在雜湊表中hashCode() 的作用是獲取物件的雜湊碼,進而確定該物件在雜湊表中的位置。

到此這篇關於一文詳解Object類和抽象類的文章就介紹到這了,更多相關Object抽象類內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!


IT145.com E-mail:sddin#qq.com