接口是一个抽象概念的实例化,它表示了一个类所能实现的方法与属性值。但在Java中,interface作为一个类型,就额外拥有了一些特点。
以下内容基于Java8书写
定义一个接口
接口被interface关键字定义且无法被final所描述,自带有abstract修饰符。在不同的位置下,接口修饰符的限制有所不同:
- 同名类文件中(独立接口),只允许
public权限修饰符,不接受static关键字。 class内部类,接受public、protect、private权限修饰符,默认且只允许static修饰符。interface内部类,自带且只允许public static abstract修饰符。
举例:
1 | public interface AInterface { |
定义接口方法
接口方法只接受public abstract修饰符,而default修饰符在接口方法中只表示默认实现,所处位置在权限修饰符后与abstract同级,因此不提供权限修饰作用。被default修饰的接口方法不再强制实现类实现。↓
1 | public interface AInterface { |
这里的BClass在实现AInterface时就不需要实现hello()方法。
定义接口属性
接口属性只能被public static final修饰(所以一般可以不写修饰符),因此存在于接口中的属性必定可以使用接口名.属性名方式进行访问。
例如java.lang.reflect.Member接口就定义了PUBLIC和DECLARED属性。↓

注意
Java8中不支持本地接口(方法中定义接口)
Java7及以前版本的接口方法无法在接口中实现(对接口方法进行default实现)
接口的使用
接口可以被实现与继承,并且接口是Java中唯一支持多继承的类型。
接口的继承
例如以下接口定义中,AInterface继承于Map、Cloneable和Serializable接口,这里需要说明一点,interface只能继承interface,class只能实现interface,interface无法继承class。↓
1 | public interface AInterface<K, V> extends Map<K, V>, Cloneable, Serializable { |
这表示,AInterface接口也继承了Map、Cloneable和Serializable接口的属性与方法,也就是说可以像使用Map、Cloneable和Serializable接口一样去使用AInterface接口。
接口的实现
比如经典的HashMap类就是实现了Map、Cloneable和Serializable接口。↓

因此,HashMap就需要实现它继承的接口的所有非default修饰方法。当然,实现类也可以重写被default修饰的方法。
作用
定义规范
接口的主要作用就是定义一个规范,就像是协议一样,让协议实现方通过接口实现的方式进行统一开发,而使用方只需要关注协议内容即可。双方都面向接口开发可以大大降低耦合度,极大地提高开发维护效率。
举例:
假设我们有一个县长接口:↓
1 | public interface Xianzhang { |
县长接口为我们提供了power和wealth两个方法。这时我们用一个类Tang来实现县长接口:↓
1 | public class Tang implements Xianzhang { |
此时,Tang就获得了县长类型,我们就可以这样来使用它:↓
1 | public static void main(String[] args) throws Exception { |
这里我们就获得了Tang的power和wealth。那么我们就有一个疑问了,为什么要使用Xianzhang tang = new Tang();为不是Tang tang = new Tang();呢,明明效果都一样啊?因为我们可能还有一个县长的实现类Wang:↓
1 | public class Wang implements Xianzhang { |
当我们没有Tang的时候,只需要把new Tang()换成new Wang()就好了,handle()方法也不需要改变,因为我们定义是以Xianzhang来定义的,我们就只需要关注Xianzhang接口为我们提供了什么方法就可以了,谁来实现都无所谓。
定义常量
很多时候我们会用到一些配置量,例如每周的天数、光速、字符串分隔符等等。
我们需要一个专有的类来管理这些全局配置,那么接口就非常适合用来存放这些静态常量:↓
1 | // 这里只做演示,常量在实际编写时需要归类,使用不同的接口管理 |
当然,并不是说静态常量都要放在接口中,只是因为放置于接口中便于维护与使用。
定义类型
定义类型的目的一般用在类筛选上,某些方法只对特殊的类做处理就可以使用空接口,例如Serializable接口:↓

当我们实现去定义类型的空接口时,就表示我们知道我们在做什么,类似于签署了一个协议。
比如我开发了一个功能,传入一个对象就可以将这个对象的所有属性值清空。但是为了避免使用者误用这个方法,我可以定义一个Clearable接口,并将clear方法入参锁定成Clearable。这样,只有继承了Clearable接口的类的实例才允许被属性清空:
1 | // 属性清空方法 |