Java基礎知識回顧之抽象類
阿新 • • 發佈:2018-12-08
簡介
如果是需要了解抽象類,就需要知道什麼普通類。對於普通類,可以直接產生例項化物件,並且在普通類之中可以包含有構造方法、普通方法、static 方法、常量、變數等內容。而所謂的抽象類就是指在普通類的結構中增加抽象方法的組成部分。
在所有的普通方法上都會有一個“{}”,這個表示方法體,有方法體的方法一定可以被物件直接使用。而抽象方式是沒有方法體的方法,同時抽象方法還必須使用 abstract 關鍵字進行定義。
擁有抽象方法的類一定屬於抽象類,抽象類要使用 abstract 關鍵字宣告。
程式碼例項說明
定義抽象類
使用 abstract 關鍵字來宣告類以及方法,抽象方法是不能有方法體的。
abstract class A{ // 定義一個抽象類
public void fun() { // 普通方法
System.out.println("這是一個普通方法");
}
// 此方法沒有方法宣告,並且使用 abstract 關鍵字,表示抽象類
public abstract void print();
}
使用抽象類
由於抽象類不能直接被例項化,比如上面的例子中,使用 A a = new A()
就會報 A是抽象類,不能被例項化的錯誤。
原因:當一個類的例項化物件之後,就意味著這個例項化物件可以呼叫類中的屬性和方法,但是在抽象類中存在有抽象方法,抽象方法是沒有方法體,是不能被呼叫的
對於抽象方法的使用原則如下:
- 抽象類必須有子類。即:每一個抽象類一定要被子類所繼承
- 抽象類的子類(子類不是抽象類)必須要覆寫抽象類之中的全部抽象方法(強制子類覆寫 )
- 抽象類的物件例項化需要依靠子類完成,採用向上轉型的方法處理
TestDemo.java
abstract class A{ // 定義一個抽象類
public void fun() { // 普通方法
System.out.println("A類中---這是一個普通方法");
}
// 此方法沒有方法宣告,並且使用 abstract 關鍵字,表示抽象類
public abstract void print();
}
// 一個子類只能繼承一個抽象類,屬於單繼承侷限
// B 類時抽象類的子類,並且是一個普通抽象類
class B extends A{
public void fun() {
System.out.println("B類中---這是一個普通方法 func()");
}
// 此處時候需要覆寫 A 類中的抽象方法,並且是強制覆寫
@Override
public void print() {
// TODO Auto-generated method stub
System.out.println("B類中---這是繼承抽象類方法 print()");
}
}
public class TestDemo {
public static void main(String[] args) {
A a = new B();
a.print();
a.fun();
}
}
控制檯輸出
B類中---這是繼承抽象類方法 print()
B類中---這是一個普通方法 func()
從上面的程式碼,可以總結出:
- 抽象類繼承子類裡面會有明確的方法覆寫要求,而普通類沒有
- 抽象類只是比普通類多了一些抽象方法的定義,其他組成部分與普通類完全一樣
- 普通類物件可以例項化,但是抽象類的物件必須經過向上轉型之後才能例項化物件使用
抽象類的相關限制
抽象類的組成和普通類的區別不大,但是在使用和定義上面會有所區別,所以以下幾點也很重要
- 抽象類也存在構造方法。抽象類裡面由於會存在一些屬性,那麼在抽象類中一定會存在構造方法。目的:為屬性初始化。並且子類物件在例項化的時候依然滿足於先執行父類構造,再執行子類構造。
- 抽象類是不能被 final 宣告。因為 final 宣告的類是不能有子類的,但是抽象類是必須依靠子類向上轉型才能例項化物件。
- 外部抽象類不能被 static 宣告,而內部的抽象類允許使用 static 宣告。使用 static 宣告的內部抽象類就相當於一個外部抽象類,繼承的時候使用“外部類.內部類”的形式表示類名稱
- 抽象類中可以使用 static 關鍵字宣告方法。
使用 static 關鍵字宣告內部的抽象類
abstract class A{ // 定義一個抽象類
// 使用 static 關鍵字定義一個內部抽象類
static abstract class B{
public abstract void print();
}
}
class X extends A.B{
// 覆寫 B類中的 print方法,這裡是強制覆寫
@Override
public void print() {
System.out.println("*********");
}
}
public class TestDemo {
public static void main(String[] args) {
// 通過內部類的方式來實現
A.B ab = new X();
ab.print(); // 輸出:*********
}
}
使用 static 關鍵字宣告抽象類中的方法
abstract class A{ // 定義一個抽象類
// 在抽象類中定義一個 static 方法
public static void print(){
System.out.println("===============");
}
}
public class TestDemo {
public static void main(String[] args) {
// 直接呼叫我們的抽象類中 static 方法
A.print(); // 輸出:===============
}
}
特殊的設計模式
在系統類庫中經常會見到以下這種設計模式。目的:為使用者隱藏不需要知道的子類。
abstract class A { // 定義一個抽象類
public abstract void print(); // 抽象方法
// 定義個私有的類來繼承 A
private static class B extends A {
// 根據抽象類的語法,這裡需要強制覆寫 A 中的 抽象方法
@Override
public void print() {
System.out.println("這個是內部子類");
}
}
// 這個方法不受例項化物件的控制
public static A getInstance(){
return new B();
}
}
public class TestDemo {
public static void main(String[] args) {
// 此時取得抽象類物件的時候,完全不需要知道 B的存在
A a = A.getInstance();
a.print();
// A.getInstance().print(); 和上面的類似
}
}
通過一個複雜的程式碼類理解
TestDemo.java
abstract class A{ // 定義一個抽象類
// 父類構造
public A() { // 2.由於 B 是繼承於A,所以先執行A類的構造
this.print(); // 3.呼叫 A類中 print 方法,但是由於A 的print方法是抽象方法,所以執行子類 B類中的 print 方法
}
public abstract void print();
}
// 一個子類只能繼承一個抽象類,屬於單繼承侷限
// B 類時抽象類的子類,並且是一個普通抽象類
class B extends A{
private int num = 100;
public B(int num) { // 5.執行完成了 A類的構造方法,就輪到執行 B中的構造方法了,此時的 num的值為 30
this.num = num;
}
@Override
public void print() {
System.out.println("num="+num); // 4.由於執行當前方法的時候,並沒有例項化出 B,並且由於 num 是int 型別,所以在列印的時候會打印出 int 型別的預設值為 0
}
}
public class TestDemo {
public static void main(String[] args) {
new B(30); // 1.執行構造方法
// new(30).print() // 這個時候就會輸出30
}
}