詳解Java抽象類與普通類的區別

淺談抽象類

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

看到這裡可能還是覺得有些難以理解,舉個例子說明一下:說到動物你會想到什麼?貓,狗,雞鴨鵝?當然這些都可以.那麼動物這兩個字,你能確定一個具體的對象嗎?顯然不能.甚至更嚴格意義上講,說到貓你會想到什麼?橘貓,短美…

畢竟:

一千個人心中有一千個哈姆雷喵.

所以我們在設計中,動物類可以設計成為抽象類,而某一種特定的物種可以采用通過繼承動物類實現.

多態這部分我理解瞭好久,有一天突然就會用瞭,也明白所謂的父類引用指向子類對象是什麼意思瞭.但是寫完前面發現,自己明白瞭講出來還是很模糊.多態真的是很重要很重要的一個點,要好好體會這部分.

抽象類和普通類的區別是什麼?

抽象類的語法規則

抽象類的語法規則:abstract關鍵字修飾

1.抽象類不可以被實例化.

2.抽象類不定有抽象方法.

3.一個類中如果有抽象方法,那麼這個類一定是抽象類.

4.抽象類中可以存在普通屬性、方法、靜態屬性和靜態方法.

5.抽象類中可以存在構造方法.

public abstract class AbstractObject{
	// 普通屬性
    String name;
	// 構造方法
    public AbstractObject(String name) {
        this.name = name;
    }
    // 靜態方法 - 類名訪問
    public static void staticMethod(){
        System.out.println("抽象類可以有靜態方法.");
    }
	// 抽象方法
    public abstract void move();
	// 普通方法
    public void commonMethod(String food){
        System.out.println("抽象類可以有普通方法.");
    }
}

抽象類不可以實例化

這部分可以直接暫時記住結論,整個過程可以暫時先跳過後面補,按照我的學習經歷(基礎差到爆),這部分直接看會很懵.

定義一個動物的抽象類,動物總得動吧(並不!)所以定義一個共性的move()方法.

public abstract class Animal {
    String name;
    public Animal(String name) {
        this.name = name;
    }
    public abstract void move();
}

當我使用IDEA寫示例的時候直接出現瞭第二種情況!見鬼瞭抽象類new出來瞭!

public class Test {
    public static void main(String[] args) {
    	// 抽象類不能實例化!會直接報編譯期錯誤!
        //標紅信息: 'Animal' is abstract; cannot be instantiated
        Animal animal = new Animal("小貓");
        // 第二種情況
        Animal animalObjcet = new Animal("小貓") {
            @Override
            public void move() {
                System.out.println("我開始移動瞭!");
            }
        };
    }
}

關於第二種情況的解釋 – 擴展知識:匿名內部類(可跳過)

這裡涉及到瞭一個知識點叫做匿名內部類.
匿名內部類的格式如下:

new 類名或者接口名(){
	重寫方法;
}
// 放到一起對比看,很明顯後面的是一個匿名內部類
new Animal("小貓") {
    @Override
    public void move() {
        System.out.println("我開始移動瞭!");
    }
};

匿名:這個類沒有名字
內部類:存在於某個類的內部的類.

它實際上是繼承並實現瞭Animal抽象類的一個子類.也就是說這裡並不是實例化出瞭Animal類,這個簡便的寫法相當於我們進行瞭如下的寫法.

public class AnimalObject extends Animal{
    public AnimalObject(String name) {
        super(name);
    }
    @Override
    public void move() {
        System.out.println("我是一隻能動的動物!");
    }
}

public class Test {
    public static void main(String[] args) {
        AnimalObject animalObject = new AnimalObject("我是動物抽象類的子類");
        animalObjcet.move();	// 我是一隻能動的動物!
    }
}

抽象類的子類

註意:這裡有一個需要強調的地方,對於抽象類中的方法我們的用詞應該是實現.對於已經實現瞭的方法,我們的用詞才可以是重寫.寫到後面發現瞭前面描述過程中我用詞都是重寫這裡進行瞭修正.
錯誤寫法:不重寫(Override)抽象類中的抽象方法
正確寫法:不實現(Implement)抽象類中的抽象方法
再次補充:好像說成重寫也不能算錯誤,IDEA自動生成的裡面也加瞭 @Override 註解.就不繼續修改瞭.

1.不實現抽象類中的抽象方法

當不對抽象類中的抽象方法進行重寫的時候,子類一定也是抽象類.(有抽象方法的類一定是抽象類)

public abstract class AbstractCat extends Animal{
    Integer weight;
    public AbstractCat(String name, Integer weight) {
        super(name);    // 繼承父類的名稱
        this.weight = weight; // 貓咪的年齡
    }
    // 這個是沒有重寫,依舊是瞭抽象方法
    public abstract void move();
    // 註意:下面這種寫法是重寫過之後的!隻是方法體為空.
    // public void move(){};
}

2.實現抽象類中的抽象方法

當對抽象類中的所有抽象方法進行實現之後,現在的貓咪類可以是一個普通類瞭.

public class Cat extends AbstractCat{
    public Cat(String name, Integer weight) {
        super(name, weight);
    }
    @Override
    public void move() {
        System.out.println("一隻奔跑的重達" + weight + "kg的" + name);
    }
}

測試一下:

public class Test {
    public static void main(String[] args) {
        Cat cat = new Cat("橘貓", 20);
        cat.move();	// 一隻奔跑的重達20kg的橘貓
    }
}

好瞭到這裡,屬於你的橘貓終於跑起來瞭!

關於實現抽象方法的延伸

我看很多文章都說要子類要重寫(重寫是錯誤的!這裡更正為實現)父類的抽象方法,抽象方法.那我如果隻實現部分抽象方法呢?
第一步:改造Animal類

public abstract class Animal {
    String name;
    public Animal(String name) {
        System.out.println("我是動物的構造方法!");
        this.name = name;
    }
    // 多添加幾個抽象方法
    public abstract void move();
    public abstract void eat();
    public abstract void sleep();
}

第二步:AbstractCat 類中實現部分抽象方法

// 不添加 abstract 關鍵字會報錯
// Class 'AbstractCat' must either be declared abstract or implement abstract method 'move()' in 'Animal'
public abstract class AbstractCat extends Animal{
    Integer weight;
    public AbstractCat(String name, Integer weight) {
        super(name);
        System.out.println("我是抽象貓咪的構造方法!");
        // 繼承父類的名稱
        this.weight = weight; // 貓咪的年齡
    }
    @Override
    public void eat() {
        System.out.println(this.name + "在吃貓糧");
    }
    @Override
    public void sleep() {
        System.out.println(this.name + "睡覺瞭!");
    }
}

第三步:Cat類登場

public class Cat extends AbstractCat{

    public Cat(String name, Integer weight) {
        super(name, weight);
    }
    /*
    sleep方法和eat方法已經在父類中實現過瞭,所以這裡隻剩下最後一個 move 是需要實現的抽象方法.
	*/
    @Override
    public void move() {
        System.out.println("重達" + weight + "kg的" + this.name + "在懶洋洋的跑");
    }
}

小結

1.普通類可以實例化調用,但是抽象類不可以,因為抽象類隻是一種概念,無法映射為具體的對象.

2.普通類和抽象類都可以被繼承,但是抽象類被繼承之後,子類需要重寫抽象類中的全部抽象方法,否則子類必須是一個抽象類.

參考和擴展閱讀

Java基礎系列第一彈之方法重載和方法重寫的區別
Java基礎系列第二彈之Java多態成員訪問的特點
Java基礎系列第三彈之操作字符串的類都有哪些?區別是什麼?

到此這篇關於詳解Java抽象類與普通類的區別的文章就介紹到這瞭,更多相關Java抽象類與普通類內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!

推薦閱讀: