Java介面方法


介面方法宣告

可以在介面中宣告三種型別的方法:

  • 抽象方法
  • 靜態方法
  • 預設方法

在Java 8之前,只能在介面中宣告抽象方法。 修飾符staticdefault用於分別宣告靜態和預設方法。
不使用staticdefault修飾符就是方法抽象。

以下是具有所有三種型別方法的介面的範例:

interface AnInterface {
  // An abstract method
  int m1();

  // A static method 
  static int m2()  {
    // The method  implementation goes  here
  }

  // A default method
  default int m3() {
    // The method implementation goes here
  }
}

抽象方法宣告

介面中的所有方法宣告都是隱式抽象和公開的,除非它們宣告為staticdefault。介面中的抽象方法沒有實現。抽象方法的主體總是由分號表示,而不是一對大括號。
下面的程式碼宣告一個名為Player的介面:

public interface Player {
  public abstract void play();

  public abstract void stop();

  public abstract void forward();

  public abstract void rewind();
}

Player 介面是音訊/視訊播放器的規範。真實的播放器,例如DVD播放器,將通過實現 Player 介面的所有四個方法來提供規範的具體實現。
在介面中使用 abstractpublic 關鍵字宣告方法中是多餘的。上面的Player介面的宣告可以改寫如下,而不改變其含義:

public interface  Player {
    void  play(); 
    void  stop(); 
    void  forward(); 
    void  rewind();
}

介面中的抽象方法宣告可以包括引數,返回型別和throws子句。

public interface NewPlayer {
  boolean play(int account) throws AccountNotFoundException;

  boolean stop(double amount);

  boolean forward(double amount) throws InsufficientBalanceException;

  double rewind();
}

介面的抽象方法由實現介面的類來實現,類重寫它們以提供方法並實現。介面中的抽象方法不能宣告為final
類可以重寫宣告介面的方法為final,指示子類不能覆蓋該方法。

靜態方法宣告

從Java 8,我們可以在介面中建立靜態方法。靜態方法包含靜態修飾符- static ,並且是隱式公開的。可以重新定義Walkable介面以包括letThemWalk()方法。

interface Walkable {
  // An abstract method 
  void walk();

  // A static convenience method
  public static void letThemWalk(Walkable[] list) {
    for (int i = 0; i < list.length; i++) {
      list[i].walk();
    }
  }
}

可以使用點表示法使用介面的靜態方法。如下程式碼 -

<interface-name>.<static-method>

與類中的靜態方法不同,介面中的靜態方法不能通過實現類或子介面來繼承。從另一個介面繼承的介面稱為子介面。 只有一種方法來呼叫介面的靜態方法:使用介面名稱。例如:
必須使用MyInterface.myStaticMethod()呼叫介面MyInterface的靜態方法myStaticMethod()

可以使用方法的非限定名稱myStaticMethod()來呼叫它,這僅在介面的主體中,或者當使用靜態import語句匯入方法時可這樣使用。

預設方法宣告

介面中的預設方法使用修辭符-default來宣告。預設方法是在Java 8中新增新功能。預設方法為實現介面的類提供了一個預設實現,但不覆蓋預設方法。
假設,有以下的一個介面。

interface Shape{
  void setX(double x);
  void setY(double y);
  double getX();
  double getY();
}

下面的程式碼顯示了 Circle 類實現了 Shape 介面。

class Circle implements Movable {
  private double x;
  private double y;

  public Circle() {
  }

  public Circle(double x, double y) {
    this.x = x;
    this.y = y;
  }

  public void setX(double x) {
    this.x = x;
  }

  public void setY(double y) {
    this.y = y;
  }

  public double getX() {
    return x;
  }

  public double getY() {
    return y;
  }

  public String toString() {
    return "Circle(" + x + ", " + y + ")";
  }
}

如果向Shape新增一個新方法如下。

interface Shape {
  void setX(double x);

  void setY(double y);

  double getX();

  double getY();

  void move(double deltaX, double deltaY);
}

在Java 8之前,新方法move()是一個抽象方法。 所有實現Shape介面的類都必須提供這個新方法的實現。
實現Shape介面的Pen類將不能通過編譯,除非將新方法新增實現到這些類中。在Java 8之前,在將介面分配給公共介面之後,在中斷實現介面方法程式碼的情況下,向介面新增方法是不可能的。
所以,引入了Java介面預設方法這個解決方案。可以將預設方法新增到現有介面,並為該方法提供預設實現而不用在實現介面的類中實現這個預設方法。

所有實現介面的類都將繼承預設實現。類可以選擇覆蓋預設實現或使用方法的預設實現。

預設方法使用關鍵字default宣告。 預設方法不能宣告為abstractstatic。 它必須提供一個實現。 否則將在編譯時發生錯誤。
以下程式碼使用預設方法更改Shape介面。

interface Movable {
  void setX(double x);

  void setY(double y);

  double getX();

  double getY();

  // 一個預設的方法
  default void move(double deltaX, double deltaY) {
    double newX = getX() + deltaX;
    double newY = getY() + deltaY;
    setX(newX);
    setY(newY);
  }
}

以下專案列出了類方法和介面預設方法之間的相似點和差異。

  • 兩者都可以以相同的方式存取關鍵字this。 關鍵字this是呼叫方法的物件的參照。
  • 類一個具體方法可以存取類的範例變數。
  • 預設方法不能存取實現介面的類的變數的範例。
  • 預設方法可以存取介面的其他成員。
  • 兩種型別的方法都可以使用它們的引數。
  • 兩個方法都可以有一個throws子句。
  • 介面中的巢狀型別宣告定義了一個新的參照型別。
  • 可以將一個類,介面,列舉和注釋宣告為巢狀型別。
  • 在介面內宣告的介面/類稱為巢狀介面/類。
  • 介面和類定義新的參照型別,因此做巢狀介面和巢狀類。
  • 巢狀介面始終通過其封裝介面存取。
  • 可以在介面中宣告一個巢狀類。

參考以下一個具有巢狀類和常數欄位的Task介面。

interface Task {
  class EmptyTask implements Task {
    private EmptyTask() {
    }
    public void runJob() {
      System.out.println("Empty...");
    }
  }
  // A constant field
  Task EMPTY_JOB = new EmptyTask();
  void runJob();
}

public class Main {
  public static void main(String[] args) {
    submitJob(Task.EMPTY_JOB);
  }
  public static void submitJob(Task job) {
    job.runJob();
  }
}

Java介面方法 # Java_interface_Methods