# 概述

接口(英文:Interface),在 JAVA 编程语言中是一个抽象类型,是抽象方法的集合,可看做是一种数据类型,没有普通方法,接口通常以 interface 来声明。一个类通过继承接口的方式,从而来继承接口的抽象方法。

接口并不是类,编写接口的方式和类很相似,但是它们属于不同的概念。类描述对象的属性和方法接口则包含类要实现的方法

除非实现接口的类是抽象类,否则该类要定义接口中的所有方法

接口无法被实例化,但是可以被实现。一个实现接口的类,必须实现接口内所描述的所有方法,否则就必须声明为抽象类。另外,在 Java 中,接口类型可用来声明一个变量,他们可以成为一个空指针,或是被绑定在一个以此接口实现的对象。

接口里面的所有方法都是抽象方法,接口里面的所有属性都是常量。在 jdk1.8 后,接口中可以使用 default 关键字修饰非抽象方法


# 声明

接口声明
[可见度] interface 接口名称 [extends 其他的接口名] {
        // 声明变量
        // 抽象方法
}
// [extends 其他的接口名] 可有可无 [extends 接口名 1,接口名 2...]
// 这里的变量只能是 public static final 变量
// 如果变量只是这样定义:String str=""; 
// 会被隐式地指定为 public static final String str;
// 因为被隐式指定为常量,所以在定义的时候就要初始化

接口的特性:因为是隐式抽象的,所以声明一个接口 / 方法的时候,就不必使用关键字 abstract 关键字。


# 接口通常用法

通常用接口来定义实现类的外观,也就是实现类的行为定义,用来约束实现类的行为。接口就相当于定义人有五官身高体重(并没有这些定义的具体实现,也就是五官到底如何身高体重如何是没有具体说明的),但实现接口类并不是只能有接口里面的方法,也就是说实现类的功能包含但不仅限于接口约束的功能。

通过使用接口,可以实现不相关类的相同行为,而不需考虑这些类之间的层次关系,接口就是实现类对外的外观。


# 思想

根据接口的作用和用途,浓缩下来,接口的思想就是 “封装隔离”

通常提到封装是指对数据的封装,但是这里的封装是指 “对被隔离体的行为的封装”,或者是 “对被隔离体的职责的封装”;而隔离指的是外部调用和内部实现,外部调用只能通过接口进行调用,而外部调用是不知道内部具体实现的,也就是说外部调用和内部实现是被接口隔离开的


# 实现接口

当类实现接口时,要实现接口中的所有方法。否则该类必须声明为抽象类

接口类
public interface interface_test1 {
    public default void sayHi(){
        System.out.println("Hi");
    }
    void sayA();
}
public interface interface_test2 {
    void sayB();
}

实现类
public class interfaceToFact implements interface_test1,interface_test2{
    public void sayA() {
    }
    public void sayB() {
    }
}
// 接口 interface_test1 中的 sayHi 方法由于是 default 修饰的
// 所以可以不需要声明
// 接口允许包含具体实现的方法,该方法称为 "默认方法",
// 默认方法使用 default 关键字修饰。
public class interfaceToFact implements 接口名称[, 其他接口名称, 其他接口名称..., ...] 
// 又或者
public abstract class interfaceToFact implements 接口名称[, 其他接口名称, 其他接口名称..., ...]

在重写接口中的声明方法的时候,需要注意:

  1. 类在实现接口的方法时,不能抛出强制性异常,只能在接口中,或者继承接口的抽象类中抛出该强制性异常。

    抛出异常
    public interface interface_test3 {
        void sayC();
    }
    public class interfaceToFact implements interface_test1{
        // 下面这个是错误的方式
        public void sayC() throws Exception{
        }
    }
    // 将接口改成下面的形式,然后在实现类里面才可以使用上面的
    public interface interface_test3 {
        void sayC() throws Exception;
    }
  2. 类在重写方法时要保持一致的方法名,并且应该保持相同或者相兼容的返回值类型。

  3. 如果实现接口的类是抽象类,那么就没必要实现该接口的方法。


# 抽象类和接口的区别

抽象类接口
变量可以是任意类型只能是 public static final
方法可以有静态方法和静态代码块;
方法可以有方法体
不能有静态方法和静态代码块
只有默认方法才有可以有方法体
继承类只能继承一个类一个接口可以继承多个接口

:JDK 1.8 以后,接口里可以有静态方法和方法体了。

区别细明

抽象类是对一种事物的抽象👉对类抽象,而接口是对行为的抽象。抽象类是对整个类整体进行抽象,包括属性、行为,但是接口却是对类局部(行为)进行抽象。抽象类是被继承,而接口是被实现,举个例子,人和海豚是不同的两种事物,但是都属于哺乳动物,人会开车,而海豚不会,那么在设计的时候可以将哺乳动物 mammal 设计成一个抽象类,开车设为一个 drive 接口,那么人 people 这个类继承 mammal 并且可以实现 drive 接口,而海豚 Dolphin 类只能继承 mammal,并不能实现 drive 接口,从这里也可以看出来,抽象类的继承是一个 “是否属于” 的关系,而接口则是 “有没有” 的关系。如果一个类继承了某个抽象类,那么这个类必然是抽象类的种类,而接口实现则是有没有、具备不具备的关系


在设计上,抽象类可以是很多子类的父类,它是一种设计模板。而接口是一种行为规范,它是一种辐射式设计。

设计模板:类似于 ppt 的模板。

辐射式设计:指以一个点为中心向四周放射出许多线构成结构的脉络。

在诸多子类继承该抽象类中,如果有共性发生了改变,那么就只需要修改抽象类即可;

而对于接口来说,如果修改接口的声明方法,那么实现该接口的类都需要改变,牵一发而动全身

# 标记接口

最常用的继承接口是没有包含任何方法的接口。

标记接口是没有任何方法和属性的接口。它仅仅表明它的类属于一个特定的类型, 供其他代码来测试允许做一些事情

标记接口作用:简单形象的说就是给某个对象打个标(盖个戳),使对象拥有某个或某些特权

例如:java.awt.event 包中的 MouseListener 接口继承的 java.util.EventListener 接口定义如下:

package java.util; 
public interface EventListener {}

没有任何方法的接口被称为标记接口。标记接口主要用于以下两种目的:

  • 建立一个公共的父接口:

    正如 EventListener 接口,这是由几十个其他接口扩展的 Java API,你可以使用一个标记接口来建立一组接口的父接口。例如:当一个接口继承了 EventListener 接口,Java 虚拟机 (JVM) 就知道该接口将要被用于一个事件的代理方案。

  • 向一个类添加数据类型:

    这种情况是标记接口最初的目的,实现标记接口的类不需要定义任何接口方法 (因为标记接口根本就没有方法),但是该类通过多态性变成一个接口类型。

# 接口的好处

由于外部调用和内部实现被接口隔离开了,那么只要接口不变,内部实现的变化就不会影响到外部应用,从而使得系统更灵活,具有更好的扩展性和可维护性,这也就是所谓 “接口是系统可插拔性的保证” 这句话的意思。

#
优先选用接口

#
在如下情况应选择抽象类:既要定义子类的行为,又要为子类提供公共的功能