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