Java 接口方法

Java面向对象设计 - Java接口方法

方法声明

您可以在接口中声明三种类型的方法:

  • 抽象方法
  • 静态方法
  • 默认方法

在Java 8之前,您只能在接口中声明抽象方法。修饰符static和default用于分别声明静态和默认方法。

缺少静态和默认修饰符使得方法抽象。

以下是具有所有三种类型方法的接口的示例:

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
  }
}

抽象方法声明

接口中的所有方法声明都是隐式抽象和公开的,除非它们声明为static或default。

接口中的抽象方法没有实现。

抽象方法的主体总是由分号表示,而不是一对大括号。

下面的代码声明一个名为Player的接口:

public interface Player {
  public abstract void play();

  public abstract void stop();

  public abstract void forward();

  public abstract void rewind();
}

播放器界面是音频/视频播放器的规范。

真实的播放器,例如DVD播放器,将通过实现播放器接口的所有四种方法来提供该规范的具体实现。

在接口中的方法声明中使用抽象和公共关键字是多余的。

上面的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,我们可以在接口中有静态方法。

静态方法包含静态修饰符,并且是隐式公开的。

我们可以重新定义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语句导入方法时。

默认方法声明

接口中的默认方法使用modifier default来声明。默认方法是在Java 8中添加新功能。

默认方法为实现接口的类提供了一个默认实现,但不重写默认方法。

假设,我们有以下接口。

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

下面的代码显示了实现Shape接口的Circle。

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 声明。默认方法不能声明为abstract或static。它必须提供一个实现。否则,将发生编译时错误。

以下代码使用默认方法更改Shape接口。

interface Movable {
  void setX(double x);

  void setY(double y);

  double getX();

  double getY();

  // A default method
  default void move(double deltaX, double deltaY) {
    double newX = getX() + deltaX;
    double newY = getY() + deltaY;
    setX(newX);
    setY(newY);
  }
}

以下项目列出了类中的具体方法和接口中的默认方法之间的相似点和差异。

两者都以相同的方式访问关键字 this 。 关键字 this 是调用该方法的对象的引用。

类中的一个具体方法可以访问类的实例变量。

默认方法不能访问实现接口的类的变量的实例。

默认方法可以访问接口的其他成员。

两种类型的方法都可以使用它们的参数。

两个方法都可以有一个throws子句。

接口中的嵌套类型声明定义了一个新的引用类型。

我们可以将一个类,接口,枚举和注释声明为嵌套类型。

在接口内声明的接口/类称为嵌套接口/类。

接口和类定义新的引用类型,因此做嵌套接口和嵌套类。

嵌套接口始终通过其封装接口访问。

我们还可以在接口中声明一个嵌套类。

具有嵌套类和常量字段的作业接口。

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();
  }
}