Java:009接口與抽象方法_抽象方法

1.抽象類

1.1

在面向對象的概念中,所有的對象都是通過類來描繪的,但是反過來,並不是所有的類都是用來描繪對象的,如果一個類中沒有包含足夠的信息來描繪一個具體的對象,這樣的類就是抽象類。 

Java:009接口與抽象方法_#開發語言_02

在打印圖形例子中, 我們發現, 父類 Shape 中的 draw 方法好像並沒有什麼實際工作, 主要的繪製圖形都是由 Shape 的各種子類的 draw 方法來完成的。像這種沒有實際工作的方法, 我們可以把它設計成一個抽象方法(abstract method), 包含抽象方法的類我們稱為抽象類(abstract class)。

Java:009接口與抽象方法_#android_03

1.2 語法

在Java中,一個如果被 abstract 修飾稱為抽象類,抽象類中被 abstract 修飾的方法稱為抽象方法抽象方法不用給出具體的實現體,只保留方法的名字參數信息。

Java:009接口與抽象方法_抽象方法_04

// 抽象類也是類,也可以增加普通方法和屬性
public abstract class Shape {
    // 抽象方法不能寫方法的具體實現  即沒有方法體

    public abstract void draw();

    // 形狀的面積. 抽象類可以包含屬性
    private double area;

    private static int n = 0;

    // 也可以包含普通的方法
    public double getArea() {
        return area;
    }

    // 也可以包含靜態方法
    public static int getCount() {
        return n;
    }
}

1.3 特性

(1)抽象類不能直接實例化對象

Java:009接口與抽象方法_#開發語言_05


(2)抽象方法不能是 private 的,也不能被final和static修飾,因為抽象方法要被子類重寫。

(3)抽象類必須被繼承,並且繼承後子類必須要重寫父類中的抽象方法(用的更多)也是抽象類(要使用 abstract 修飾)。

(4)抽象類中不一定包含抽象方法,但是有抽象方法的類一定是抽象類

(5)抽象類中可以有構造方法供子類創建對象時,初始化父類的成員變量。

Java:009接口與抽象方法_抽象類_06

1.4

Java:009接口與抽象方法_抽象類_07


Java:009接口與抽象方法_抽象類_08

2.接口

2.1 概念

在現實生活中,接口的例子比比皆是,比如:筆記本上的USB口,電源插座等。

電腦的USB口上,可以插:U盤、鼠標、鍵盤...所有符合USB協議的設備;電源插座插孔上,可以插:電腦、電視機、電飯煲...所有符合規範的設備。

通過上述例子可以看出:接口就是公共的行為規範標準,大家在實現時,只要符合規範標準,就可以通用。

在Java中,接口可以看成多個類的公共規範,是一種引用數據類型


Java:009接口與抽象方法_抽象類_09


2.2

接口的定義格式與定義類的格式基本相同,將class關鍵字換成 interface 關鍵字,就定義了一個接口。

Java:009接口與抽象方法_#android_10

// 對於接口來説, 裏面不能包含屬性, 
// 包含的方法也只能是抽象方法.
public interface Drawable {
    void draw();
}

Java:009接口與抽象方法_抽象類_11

public interface Drawable {
    public static final int count = 0;

    void draw();
}

2.3

接口不能直接使用,必須要有一個 "實現類" 來 "實現" 該接口,實現接口中的所有抽象方法。

Java:009接口與抽象方法_#java_12

注意:子類和父類之間是extends 繼承關係,類與接口之間是 implements 實現關係。


Java:009接口與抽象方法_抽象類_13

public class Mouse implements USB {
    @Override
    public void openDevice() {
        System.out.println("插入鼠標");
    }

    @Override
    public void closeDevice() {
        System.out.println("拔出鼠標");
    }
}
public class KeyBoard implements USB {

    @Override
    public void openDevice() {
        System.out.println("插入鍵盤");
    }

    @Override
    public void closeDevice() {
        System.out.println("拔出鍵盤");
    }
}
public class Test {
    public static void main(String[] args) {
        USB usb = new Mouse();
        usb.openDevice();
        usb.closeDevice();

        usb = new KeyBoard();
        usb.openDevice();
        usb.closeDevice();
    }
}

2.4

(1) 接口類型是一種引用類型,但是不能直接new接口的對象。

(2)接口中每一個方法都是public的抽象方法, 即接口中的方法會被隱式的指定為 public abstract(只能是 public abstract,其他修飾符都會報錯)。

(3)接口中的方法不能接口中實現的,只能由實現接口的類來實現。

(4)重寫接口中方法時,不能使用默認的訪問權限

Java:009接口與抽象方法_#java_14

(5)接口中可以含有變量,但是接口中的變量會被隱式的指定為 public static final 變量。

(6)接口中不能靜態代碼塊和構造方法

Java:009接口與抽象方法_抽象方法_15

(7)接口雖然不是類,但是接口編譯完成後字節碼文件的後綴格式也是.class

Java:009接口與抽象方法_抽象方法_16

(8)如果類沒有實現接口中的所有的抽象方法,則類必須設置為抽象類

Java:009接口與抽象方法_抽象方法_17

(9)jdk8中:接口中還可以包含default方法

Java:009接口與抽象方法_#android_18


Java:009接口與抽象方法_#android_19


2.5

在Java中,類和類之間是單繼承的,一個類只能有一個父類,即Java中不支持多繼承但是一個類可以實現多個接口。

Java:009接口與抽象方法_#android_20


下面通過類來表示一組動物,另外我們再提供一組接口, 分別表示 "會跑的", "會游泳的"。

Java:009接口與抽象方法_抽象方法_21


注意:一個類實現多個接口時,每個接口中的抽象方法都要實現,否則類必須設置為抽象類。

提示,:IDEA 中使用 ctrl + i 快速實現接口         

Java:009接口與抽象方法_抽象類_22


Java:009接口與抽象方法_#開發語言_23


2.6

Java:009接口與抽象方法_#開發語言_24


Java:009接口與抽象方法_#java_25


2.7

Java:009接口與抽象方法_#java_26


Java:009接口與抽象方法_抽象類_27


Java:009接口與抽象方法_#android_28


Java:009接口與抽象方法_#android_29


兩種方式對比

Java:009接口與抽象方法_#開發語言_30


2.8

(1)Clonable 接口

Java 中內置了一些很有用的接口, Clonable 就是其中之一。

Object 類中存在一個 clone 方法, 調用這個方法可以創建一個對象的 "拷貝"。但是要想合法調用 clone 方法, 必須要先實現 Clonable 接口, 否則就會拋出 CloneNotSupportedException 異常

Java:009接口與抽象方法_抽象類_31


Java:009接口與抽象方法_#java_32


Java:009接口與抽象方法_抽象類_33


Java:009接口與抽象方法_#android_34


(2)淺拷貝vs深拷貝

Cloneable 拷貝出的對象是一份 "淺拷貝"

Java:009接口與抽象方法_#java_35


Java:009接口與抽象方法_#android_36


Java:009接口與抽象方法_抽象類_37


Java:009接口與抽象方法_#android_38


2.9 抽象類和接口的區別

Java:009接口與抽象方法_抽象類_39


Java:009接口與抽象方法_抽象方法_40

3.匿名內部類

Java:009接口與抽象方法_抽象方法_41


Java:009接口與抽象方法_抽象類_42


import java.util.Comparator;

public class Test4 {
    public static void main(String[] args) {
        // 需要給 Test4 這個類, 創建 Comparator 比較器

        Comparator<Test4> comparator = new Comparator<Test4>() {
            @Override
            public int compare(Test4 o1, Test4 o2) {
                return 0;
            }
        };

        Test4 t1 = new Test4();
        Test4 t2 = new Test4();
        int ret = comparator.compare(t1, t2);
        System.out.println(ret);
    }
}

4.Object類

Object是Java默認提供的一個類。Java裏面除了Object類,所有的類都是存在繼承關係的,默認繼承Object父類,所有類的對象都可以使用 Object 的引用進行接收。

所以在開發之中,Object 類是參數的最高統一類型,且 Object 類也存在有定義好的一些方法

Java:009接口與抽象方法_抽象類_43


4.1

如果要打印對象中的內容,可以直接重寫 Object 類中的 toString() 方法,之前已經講過了,此處不再累贅。

Java:009接口與抽象方法_抽象方法_44


Java 中的引用類型主要包括:
類型(內置類【String 類、包裝類、系統類】、自定義類)、接口類型、數組類型、枚舉類型、註解類型。

所有引用類型的共同特點是:變量存儲的是對象內存地址,而不是對象本身這是理解 Java 面向對象編程和內存管理的關鍵。

4.2 equals--對象比較

Java:009接口與抽象方法_#android_45


Java:009接口與抽象方法_抽象方法_46

在Java中比較對象:

== 運算符用於比較兩個對象的引用是否指向同一塊內存地址【內存角度】或   兩個引用變量是否指向同一個對象(即內存地址是否相同)【對象角度

equals 方法默認情況下(在Object類中)也是比較引用是否相同,即與 == 的行為相同

但是,許多類(如 String 類)重寫equals 方法,此時就會去比較兩個字符串的內容是否相同,而不是比較它們是否指向同一個對象

Java:009接口與抽象方法_#android_47


Java:009接口與抽象方法_#java_48


結論:比較對象中內容是否相同的時候,一定要重寫equals方法。

代碼

public class LianXi {
    public static void main(String[] args) {
        Student s1 = new Student(1, "張三", 90);
        Student s2 = new Student(1, "張三", 90);
        // 此處針對上述對象是比較兩個引用的指向是否相同,不相同
        System.out.println(s1 == s2);       //false

        // 若想比較內容, 就可以使用 equals 方法
        // 但Object 中默認的 equals 還是比較 ==
        // 比較內容就需要根據具體的類, 重寫 equals 方法! 在Student中
        System.out.println(s1.equals(s2));  //true
    }
}
public class Student {
    private int id;
    private String name;
    private double score;

    public Student(int id, String name, double score) {
        this.id = id;
        this.name = name;
        this.score = score;
    }
    //……get set 方法

    @Override
    public boolean equals(Object o) {
        if (o == null) {
            // this 肯定不是 null
            return false;
        }
        if (this == o) {
            // 如果兩個引用指向同一個對象, 當然值也是相等的
            return true;
        }
        if (!(o instanceof Student)) {
            // 使用 instanceof 檢查傳入對象是否是 Student 類型或其子類
            // !  傳入的參數類型和當前 Student 不匹配.
            return false;
        }

        // 只比較兩個 Student 的id 字段,認為學號相同就是同一個學生 
        // 將對象轉換為 Student 類型
        Student other = (Student) o;
        return this.id == other.id;
    }
}

Java:009接口與抽象方法_抽象方法_49

Java:009接口與抽象方法_#開發語言_50