1. 程式人生 > >Java_抽象類和介面

Java_抽象類和介面

Java 抽象類


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

抽象類除了不能例項化物件之外,類的其它功能依然存在,成員變數、成員方法和構造方法的訪問方式和普通類一樣。

由於抽象類不能例項化物件,所以抽象類必須被繼承,才能被使用。也是因為這個原因,通常在設計階段決定要不要設計抽象類。

父類包含了子類集合的常見的方法,但是由於父類本身是抽象的,所以不能使用這些方法。

在Java中抽象類表示的是一種繼承關係,一個類只能繼承一個抽象類,而一個類卻可以實現多個介面。


抽象類和抽象類的繼承

在Java語言中使用abstract class來定義抽象類。如下例項:

Test1.java 檔案程式碼:

public class Test1 {
public static void main(String[] args) {
// TODO Auto-generated method stub
//Animals a=new Animals();//抽象類不可以例項化
Animals b=new Birds();//向上造型
b.act();
}


}
/*
 * 用abstract修飾的類就是抽象類,和普通類基本沒區別,但抽象類裡面可以寫抽象方法
 * 用abstract修飾的方法為抽象方法,抽象方法只有方法的定義,沒有方法的具體實現,用一個分號結尾
 */
abstract class Animals{
int age;
String gender;
public Animals() {
super();
}
public Animals(int age, String gender) {
super();
this.age = age;
this.gender = gender;
}
//抽象類裡面的抽象方法
public abstract void act();//抽象方法只有方法的宣告,沒有方法的具體實現(即沒有方法體),用分號結束
public void breed(){//在抽象類裡面可以寫普通方法
System.out.println("繁殖");
}
}
class Birds extends Animals{
//如果一個類繼承了抽象類,必須重寫其抽象方法
public void act() {
System.out.println("鳥在天上飛");
}

}


class Lions extends Animals{
public void act(){
System.out.println("獅子在地上跑");
}
}

抽象類總結規定

  • 1. 抽象類不能被例項化(初學者很容易犯的錯),如果被例項化,就會報錯,編譯無法通過。只有抽象類的非抽象子類可以建立物件。

  • 2. 抽象類中不一定包含抽象方法,但是有抽象方法的類必定是抽象類。

  • 3. 抽象類中的抽象方法只是宣告,不包含方法體,就是不給出方法的具體實現也就是方法的具體功能。

  • 4. 構造方法,類方法(用static修飾的方法)不能宣告為抽象方法。

  • 5. 抽象類的子類必須給出抽象類中的抽象方法的具體實現,除非該子類也是抽象類。

Java 介面

介面(英文:Interface),在JAVA程式語言中是一個抽象型別,是抽象方法的集合,介面通常以interface來宣告。一個類通過繼承介面的方式,從而來繼承介面的抽象方法。

介面並不是類,編寫介面的方式和類很相似,但是它們屬於不同的概念。類描述物件的屬性和方法。介面則包含類要實現的方法。

除非實現介面的類是抽象類,否則該類要定義介面中的所有方法。

介面無法被例項化,但是可以被實現。一個實現介面的類,必須實現介面內所描述的所有方法,否則就必須宣告為抽象類。另外,在 Java 中,介面型別可用來宣告一個變數,他們可以成為一個空指標,或是被繫結在一個以此介面實現的物件。

介面與類相似點:

  • 一個介面可以有多個方法。
  • 介面檔案儲存在 .java 結尾的檔案中,檔名使用介面名。
  • 介面的位元組碼檔案儲存在 .class 結尾的檔案中。
  • 介面相應的位元組碼檔案必須在與包名稱相匹配的目錄結構中。

介面與類的區別:

  • 介面不能用於例項化物件。
  • 介面沒有構造方法。
  • 介面中所有的方法必須是抽象方法。
  • 介面不能包含成員變數,除了 static 和 final 變數。
  • 介面不是被類繼承了,而是要被類實現。
  • 介面支援多重繼承。

介面特性

  • 介面中每一個方法也是隱式抽象的,介面中的方法會被隱式的指定為 public abstract(只能是 public abstract,其他修飾符都會報錯)。
  • 介面中可以含有變數,但是介面中的變數會被隱式的指定為 public static final 變數(並且只能是 public,用 private 修飾會報編譯錯誤。
  • 介面中的方法是不能在介面中實現的,只能由實現介面的類來實現介面中的方法。

抽象類和介面的區別

  • 1. 抽象類中的方法可以有方法體,就是能實現方法的具體功能,但是介面中的方法不行。
  • 2. 抽象類中的成員變數可以是各種型別的,而介面中的成員變數只能是 public static final 型別的。
  • 3. 介面中不能含有靜態程式碼塊以及靜態方法(用 static 修飾的方法),而抽象類是可以有靜態程式碼塊和靜態方法。
  • 4. 一個類只能繼承一個抽象類,而一個類卻可以實現多個介面。

介面的宣告和實現

介面的宣告語法格式如下:

[ 可見度 ] interface 介面名稱 [ extends 其他的類名 ] { // 宣告變數 // 抽象方法 }

當類實現介面的時候,類要實現介面中所有的方法。否則,類必須宣告為抽象的類。

類使用implements關鍵字實現介面。在類宣告中,Implements關鍵字放在class聲明後面。

實現一個介面的語法,可以使用這個公式:

Animal.java 檔案程式碼:

... implements 介面名稱 [ , 其他介面, 其他介面..., ... ] ...

Interface關鍵字用來宣告一個介面。下面是介面宣告的一個簡單例子。

Test2.java 檔案程式碼:

public class Test2 {
public static void main(String[] args) {
//Runner r=new Runner();介面不能例項化
Hunter c=new Chinese();//父類的引用指向子類的物件
c.run();
c.hunt();
}


}
//介面
//介面可以看成是一個特殊的抽象類,即只有抽象方法的抽象類
interface Runner{
//接口裡定義的屬性都是常量
public static final int DEFAULT_SPEED=100;
int AGE=20;//public static final預設存在
public abstract void run();//介面中只能定義抽象方法
void swim();//public abstract 預設存在
}
interface Hunter extends Runner{//介面與介面之間是繼承關係
void hunt();//public abstract 預設存在
}
class Chinese implements Hunter{//類與介面之間是implements實現關係
//需要重寫介面中的抽象方法
public void run() {
System.out.println("中國人跑步");
}


public void swim() {
System.out.println("中國人游泳");
}


public void hunt() {
System.out.println("中國人打獵");
}
//public abstract void run1();如果一個類裡面有抽象方法,這個類也是抽象的
}
abstract class American implements Hunter{
//抽象類實現介面時可以不用重寫抽象方法
// public abstract void hunt();
// public abstract void swim();
// public abstract void run();
}

介面有以下特性:

  • 介面是隱式抽象的,當宣告一個介面的時候,不必使用abstract關鍵字。
  • 介面中每一個方法也是隱式抽象的,宣告時同樣不需要abstract關鍵子。
  • 介面中的方法都是公有的。

介面的實現

當類實現介面的時候,類要實現介面中所有的方法。否則,類必須宣告為抽象的類。

類使用implements關鍵字實現介面。在類宣告中,Implements關鍵字放在class聲明後面。

實現一個介面的語法,可以使用這個公式:

Animal.java 檔案程式碼:

... implements 介面名稱 [ , 其他介面, 其他介面..., ... ] ...

例項

MammalInt.java 檔案程式碼:

/* 檔名 : MammalInt.java */ public class MammalInt implements Animal { public void eat ( ) { System . out . println ( " Mammal eats " ) ; } public void travel ( ) { System . out . println ( " Mammal travels " ) ; } public int noOfLegs ( ) { return 0 ; } public static void main ( String args [ ] ) { MammalInt m = new MammalInt ( ) ; m . eat ( ) ; m . travel ( ) ; } }

以上例項編譯執行結果如下:

Mammal eats
Mammal travels

重寫介面中宣告的方法時,需要注意以下規則:

  • 類在實現介面的方法時,不能丟擲強制性異常,只能在介面中,或者繼承介面的抽象類中丟擲該強制性異常。
  • 類在重寫方法時要保持一致的方法名,並且應該保持相同或者相相容的返回值型別。
  • 如果實現介面的類是抽象類,那麼就沒必要實現該介面的方法。

在實現介面的時候,也要注意一些規則:

  • 一個類可以同時實現多個介面。
  • 一個類只能繼承一個類,但是能實現多個介面。
  • 一個介面能繼承另一個介面,這和類之間的繼承比較相似。

Java的單繼承和多實現

在Java中,類的多重繼承是不合法,但介面允許多實現,。

在介面的多重繼承中extends關鍵字只需要使用一次,在其後跟著繼承介面。 如下所示:

public class Test3 {
public static void main(String[] args) {
Me m=new Me();
m.teach();
m.iron();
m.work();
}
}
interface Teacher{
public void teach();
}
interface Blacksmith{
public void iron();
}
 abstract class Worker{
public abstract void work();
}
 //介面和類   相同的用extends,不同的用implements
//繼承只能單繼承
//介面可以多實現
class Me extends Worker implements Teacher,Blacksmith {
public void teach(){
System.out.println("實現授課");
}
public void iron(){
System.out.println("實現打鐵");
}
public void work() {
System.out.println("實現工作");
}
}

標記介面

最常用的繼承介面是沒有包含任何方法的介面。

標識介面是沒有任何方法和屬性的介面.它僅僅表明它的類屬於一個特定的型別,供其他程式碼來測試允許做一些事情。

標識介面作用:簡單形象的說就是給某個物件打個標(蓋個戳),使物件擁有某個或某些特權。

例如:java.awt.event 包中的 MouseListener 介面繼承的 java.util.EventListener 介面定義如下:

package java . util ; public interface EventListener { }

沒有任何方法的介面被稱為標記介面。標記介面主要用於以下兩種目的:

  • 建立一個公共的父介面:

    正如EventListener介面,這是由幾十個其他介面擴充套件的Java API,你可以使用一個標記介面來建立一組介面的父介面。例如:當一個介面繼承了EventListener介面,Java虛擬機器(JVM)就知道該介面將要被用於一個事件的代理方案。

  • 向一個類新增資料型別:

    這種情況是標記介面最初的目的,實現標記介面的類不需要定義任何介面方法(因為標記介面根本就沒有方法),但是該類通過多型性變成一個介面型別。