Java 简明教程

Java - Interfaces

Java Interfaces

Java 接口是抽象方法的集合。该接口用于实现 abstraction,在其中您可以定义方法,但没有其实现(没有方法的主体)。接口是一种引用类型,类似于 class

除了抽象方法,接口还可能包含常数、默认 methods、静态方法和嵌套类型。只有对默认方法和静态方法存在方法主体。

编写接口类似于编写类。但是,类描述对象的 attributes 和行为。接口包含类实现的行为。除非实现该接口的类是抽象类,否则在类中需要定义接口的所有方法。

Java Interfaces and Classes: Similarities and Differences

Similarities

接口在以下方面类似于类 -

  1. 接口可以包含任意数量的方法。

  2. 接口是用 .java 扩展名写入文件的,接口的名称与文件的名称相匹配。

  3. 接口的字节码出现在 .class 文件中。

  4. 接口出现在包中,其对应的字节码文件必须位于与包名称相匹配的目录结构中。

Differences

然而,接口在以下几个方面与类不同,包括 -

  1. 您不能实例化接口。

  2. 接口不包含任何构造函数。

  3. 接口中的所有方法都是抽象方法。

  4. 接口不能包含实例字段。接口中出现的唯一字段必须同时声明为 static 和 final。

  5. 接口不由类扩展;它由类实现。

  6. 接口可以扩展多个接口。

Declaring an Interface in Java

interface 关键字用于声明接口。以下是声明接口的一个简单示例 −

Example to Declare a Java Interface

以下是接口示例 −

/* File name : NameOfInterface.java */
import java.lang.*;
// Any number of import statements

public interface NameOfInterface {
   // Any number of final, static fields
   // Any number of abstract method declarations\
}

Propeties of Java Interface

接口具有以下属性 −

  1. 接口是隐式抽象的。声明接口时无需使用 abstract 关键字。

  2. 接口中的每个方法也是隐式抽象的,因此不需要 abstract 关键字。

  3. 接口中的方法是隐式公有的。

Example

/* File name : Animal.java */
interface Animal {
   public void eat();
   public void travel();
}

Implementing Interfaces in Java

当一个类实现一个接口时,可以将该类视为在签署一份合约,同意执行接口的特定行为。如果一个类没有执行接口的所有行为,则该类必须声明自身为抽象的。

类使用 implements 关键字来实现接口。implements 关键字出现在类声明中,紧跟声明的 extends 部分。

Example: Implement an Interface in Java

/* File name : 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();
   }
}
interface Animal {
   public void eat();
   public void travel();
}
Mammal eats
Mammal travels

Rules for defining overriding methods in Java Interfaces

当在接口中定义 overriding methods 时,需要遵循以下几条规则 −

  1. 未捕获异常不应在实现方法中声明,除非在接口方法中声明的方法或其子类中声明。

  2. 覆写方法时,应保留接口方法的签名和相同的返回类型或子类型。

  3. 实现类本身可以是抽象的,如果它是抽象的,则无需实现接口方法。

Rules for implementing Java Interfaces

实现接口时,有以下几个规则 −

  1. 一个类一次可以实现多个接口。

  2. 一个类只能扩展一个类,但可以实现多个接口。

  3. 接口可以扩展另一个接口,就像一个类可以扩展另一个类一样。

Extending Java Interfaces

接口可以扩展另一个接口,就像一个类可以扩展另一个类一样。*extends*关键字用于扩展接口,子接口继承父接口的方法。

Example: How to Extend Java Interface

以下的 Sports 接口被 Hockey 和 Football 接口扩展。

// Filename: Sports.java
public interface Sports {
   public void setHomeTeam(String name);
   public void setVisitingTeam(String name);
}

// Filename: Football.java
public interface Football extends Sports {
   public void homeTeamScored(int points);
   public void visitingTeamScored(int points);
   public void endOfQuarter(int quarter);
}

// Filename: Hockey.java
public interface Hockey extends Sports {
   public void homeGoalScored();
   public void visitingGoalScored();
   public void endOfPeriod(int period);
   public void overtimePeriod(int ot);
}

Hockey 接口有四个方法,但它从 Sports 继承了两个方法;因此,实现 Hockey 的类需要实现所有六个方法。类似地,实现 Football 的类需要定义 Football 中的三个方法和 Sports 中的两个方法。

Example

interface Sports {
   public void setHomeTeam(String name);
   public void setVisitingTeam(String name);
}

interface Football extends Sports {
   public void homeTeamScored(int points);
   public void visitingTeamScored(int points);
   public void endOfQuarter(int quarter);
}

interface Hockey extends Sports {
   public void homeGoalScored();
   public void visitingGoalScored();
   public void endOfPeriod(int period);
   public void overtimePeriod(int ot);
}

public class HockeyDemo implements Hockey {

   public void setHomeTeam(String name) {
      System.out.println("Home team: " + name);
   }

   public void setVisitingTeam(String name) {}

   public void homeGoalScored() {}

   public void visitingGoalScored() {}

   public void endOfPeriod(int period) {}

   public void overtimePeriod(int ot) {}

   public static void main(String[] args) {
      Hockey hockeyDemo = new HockeyDemo();
      hockeyDemo.setHomeTeam("India");
   }
}
Home team: India

Extending Multiple Java Interfaces

Java 类只能扩展一个父类。不允许多重继承。但是,接口不是类,并且一个接口可以扩展多个父接口。

extends 关键字只用一次,父接口在一个逗号分隔的列表中声明。

例如,如果 Hockey 接口同时扩展 Sports 和 Event,它将被声明为 −

public interface Hockey extends Sports, Event

Example: How to Extend Multiple Java Interface

interface Sports {
   public void setHomeTeam(String name);
   public void setVisitingTeam(String name);
}

interface Football extends Sports {
   public void homeTeamScored(int points);
   public void visitingTeamScored(int points);
   public void endOfQuarter(int quarter);
}

interface Hockey extends Sports {
   public void homeGoalScored();
   public void visitingGoalScored();
   public void endOfPeriod(int period);
   public void overtimePeriod(int ot);
}

interface Event {
   public void organize();
}
public class HockeyDemo implements Hockey, Event {

   public void setHomeTeam(String name) {
      System.out.println("Home team: " + name);
   }

   public void setVisitingTeam(String name) {}

   public void homeGoalScored() {}

   public void visitingGoalScored() {}

   public void endOfPeriod(int period) {}

   public void overtimePeriod(int ot) {}

   public static void main(String[] args) {
      HockeyDemo hockeyDemo = new HockeyDemo();
      hockeyDemo.setHomeTeam("India");
      hockeyDemo.organize();
   }

   public void organize() {
      System.out.println("Match organized. ");
   }
}
Home team: India
Match organized.

Tagging Java Interfaces

扩展接口最常见的用法是当父接口不包含任何方法时。例如,java.awt.event 包中的 MouseListenter 接口扩展了 java.util.EventListener,它被定义为 −

Example

package java.util;
public interface EventListener
{}

没有方法的接口被称为*tagging*接口。标记接口有两个基本设计目的 −

Creates a common parent − 与 EventListener 接口一样(Java API 中的其他数十个接口对其进行了扩展),您可以使用标记接口在接口组之间创建公共父接口。例如,当接口扩展 EventListener 时,JVM 知道该特定接口将在事件委托场景中使用。

Adds a data type to a class − 这是术语“标记”的由来。实现标记接口的类不需要定义任何方法(因为该接口没有任何方法),但该类通过多态性成为接口类型。