Java 中的接口
接口是 Java 中的引用类型。它类似于类,是抽象方法的集合。类实现接口,从而继承接口的抽象方法。
除了抽象方法外,接口还可以包含常量、默认方法、静态方法和嵌套类型。方法体只存在于默认方法和静态方法中。
编写接口与编写类类似。但类描述的是对象的属性和行为。接口包含类实现的行为。
除非实现接口的类是抽象的,否则接口的所有方法都需要在类中定义。
接口与类在以下方面相似 −
接口可以包含任意数量的方法。
接口编写在扩展名为 .java 的文件中,接口名称与文件名一致。
接口的字节码出现在 .class 文件中。
接口出现在包中,其对应的字节码文件必须位于与包名称匹配的目录结构中。
但是,接口与类在几个方面有所不同,包括 −
无法实例化接口。
接口不包含任何构造函数。
接口中的所有方法都是抽象的。
接口不能包含实例字段。接口中唯一可以出现的字段必须声明为 static 和 final。
接口不能由类扩展;它由类实现。
一个接口可以扩展多个接口。
声明接口
使用 interface 关键字来声明接口。这是一个声明接口 − 的简单示例
示例
以下是一个接口 − 的示例
/* 文件名:NameOfInterface.java */ import java.lang.*; // 任意数量的 import 语句 public interface NameOfInterface { // 任意数量的 final 静态字段 // 任意数量的抽象方法声明\ }
接口具有以下属性 −
接口是隐式抽象的。声明接口时无需使用 abstract 关键字。
接口中的每个方法也是隐式抽象的,因此不需要使用 abstract 关键字。
接口中的方法隐式公开。
示例
/* 文件名:Animal.java */ interface Animal { public void eat(); public void travel(); }
实现接口
当一个类实现一个接口时,你可以将该类视为签署一份契约,同意执行该接口的特定行为。如果一个类没有执行该接口的所有行为,则该类必须将自身声明为抽象类。
类使用 implements 关键字来实现接口。implements 关键字出现在类声明中,紧跟在声明的 extends 部分之后。
示例
/* 文件名: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
重写接口中定义的方法时,需要遵循以下几条规则 −
除了接口方法声明的方法或其子类中声明的方法之外,不应在实现方法上声明受检异常。
重写方法时,应保持接口方法的签名以及相同的返回类型或子类型。
实现类本身可以是抽象的,如果是抽象类,则无需实现接口方法。
实现接口时,需要遵循以下几条规则 −
一个类可以同时实现多个接口。
一个类只能扩展一个类,但可以实现多个接口。
一个接口可以扩展另一个接口,就像一个类可以扩展另一个接口一样类。
扩展接口
接口可以扩展另一个接口,就像类可以扩展另一个类一样。extends 关键字用于扩展接口,子接口继承父接口的方法。
以下 Sports 接口由 Hockey 和 Football 接口扩展。
示例
// 文件名:Sports.java public interface Sports { public void setHomeTeam(String name); public void setVisitingTeam(String name); } // 文件名: Football.java public interface Football extends Sports { public void homeTeamScored(int points); public void visitingTeamScored(int points); public void endOfQuarter(int quarter); } // 文件名: 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 接口的两个方法。
扩展多个接口
一个 Java 类只能扩展一个父类。不允许多重继承。然而,接口不是类,一个接口可以扩展多个父接口。
extends 关键字仅使用一次,父接口以逗号分隔的列表形式声明。
例如,如果 Hockey 接口同时扩展了 Sports 和 Event,则应将其声明为 −
示例
public interface Hockey extends Sports, Event
标记接口
扩展接口最常见的情况是父接口不包含任何方法。例如,java.awt.event 包中的 MouseListener 接口扩展了 java.util.EventListener,后者的定义为 −
示例
package java.util; public interface EventListener {}
不包含任何方法的接口称为标记接口。标记接口有两个基本设计目的 −
创建公共父类 − 与 EventListener 接口(Java API 中有很多其他接口都扩展了该接口)一样,您可以使用标记接口在一组接口中创建公共父类。例如,当一个接口扩展了 EventListener 接口时,JVM 知道这个特定的接口将用于事件委托场景。
向类添加数据类型 − 这就是术语"标记"的由来。实现标记接口的类不需要定义任何方法(因为接口本身没有任何方法),但该类通过多态性变成了接口类型。