Skip to content

接口

在抽象类中,抽象方法本质上是定义一种规范:即规定抽象的规范,从而确保所有子类都能有相同的实现。

java
abstract class Person {
  public abstract void run();
  
  public abstract String getName();
}

如果一个抽象类没有字段,所有方法都是抽象方法,那么此时可以把抽象类改写为 interface 接口:

java
interface Person {
  public abstract void run();

  public abstract String getName();
}

所谓 interface,就是比 抽象类还要抽象的抽象接口。接口中可以定义字段和方法:

  • 定义字段:必须使用 public static final 修饰;
  • 定义方法:必须使用 public abstract 修饰;

由于所有的字段和方法修饰符都是固定的,所以修饰符可以省略不写。

java
interface Person {
  //public static final String name = "";
  String name = "";

  //public static final int age = 0;
  int age = 0;

  //public abstract void run();
  void run();

  //public abstract String getName();
  String getName();
}

类实现接口

当一个 class 实现一个 interface 时,需要使用 implements 关键字。

java
class Student implements Person {
  private String name;

  public Student(String name) {
    this.name = name;
  }

  //必须要实现接口中定义的方法
  @Override
  public void run() {
    System.out.println("Student running.");
  }

  @Override
  public String getName() {
    return this.name;
  }
}

在 java 中,一个类只能继承自另一个类,不能继承多个类。但是,一个类可以继承自多个 interface

java
class Student implements Person, Person2, Person3 {
  //...
}

同时,当子类即继承了父类,又实现了接口时,一般先继承父类,再实现接口:

java
interface Person {
  void run();

  String getName();
}

class father {
}

class Student extends father implements Person {
  @Override
  public void run() {
  }

  @Override
  public String getName() {
    return "";
  }
}

接口继承接口

一个 interface 接口可以使用 extends 关键字继承另一个 interface 接口。

java
interface Hello {
  void hello();
}

interface Person extends Hello {
  void run();
  String getName();
}

此时,Person 接口实际上拥有了 3 个抽象方法,其中 hello() 来自于继承的接口。

JDK8新特性

静态方法

JDK8 以后,接口中可以定义静态方法,该方法只能接口自己调用。

java
public static void main(String[] args) {
  Person.method();
}

interface Person {
  public static void method() {
    System.out.println("我是静态方法");
  }
}

默认方法

JDK8 以后,接口中可以使用 default 关键字定义默认方法,子类实现接口时,可以不用立即实现默认方法,在需要的时候实现即可。

java
public static void main(String[] args) {
  Student student = new Student();
  
  //Student子类没有实现 method 方法,这时候会走接口中定义的 method 方法
  student.method();	//我是Person接口中的默认方法.
}

interface Person {
  public default void method() {
    System.out.println("我是Person接口中的默认方法.");
  }
}

class Student implements Person {
}
java
public static void main(String[] args) {
  Student student = new Student();

  //Student子类实现了 method 方法,这时候会子类中的 method 方法
  student.method();	//我是Student子类的默认方法.
}

interface Person {
  public default void method() {
    System.out.println("我是Person接口中的默认方法.");
  }
}

class Student implements Person {
  @Override
  public void method2() {
    System.out.println("我是Student子类的默认方法.");
  }
}

接口冲突

当 A 接口中有 method 方法,而 B 接口中也有一个和 A 一模一样的 method 方法时,实现类即继承了 A,也继承了 B,这时候实现类就会报错,因为不知道 method 方法到底是继承自谁的,所以,此时实现类就必须手动重写 method 方法。

java
interface Person {
  public default void method() {
    System.out.println("Person");
  }
}

interface Person2 {
  public default void method() {
    System.out.println("Person2");
  }
}

class Student implements Person, Person2 { //报错: 不知道要继承谁的 method 方法
}

class Student implements Person, Person2 { //正确: 因为重写了 method 方法,调用时就会走 Student 类的方法
  @Override
  public void method() {
    System.out.println("student");
  }
}

这种情况下,如果 Student 类的 method 方法中,就想要调用 父接口中的 method 方法,可以使用 Person.super.method 方式。

java
public static void main(String[] args) {
  Student student = new Student();
  student.method(); //Person Person2都打印
}

interface Person {
  public default void method() {
    System.out.println("Person");
  }
}

interface Person2 {
  public default void method() {
    System.out.println("Person2");
  }
}

class Student implements Person, Person2 {
  @Override
  public void method() {
    Person.super.method();
    Person2.super.method();
  }
}

类和接口优先级

当一个类即继承了父类,又实现了接口,而父类中和接口中存在相同的方法,这时候 父类的优先级更高。

java
public class interfaceTest {
  public static void main(String[] args) {
    Student student = new Student();
    
    //父类的优先级更高
    student.method2(); //Person2
  }
}

interface Person {
  public default void method2() {
    System.out.println("Person");
  }
}

class Person2 {
  public void method2() {
    System.out.println("Person2");
  }
}

class Student extends Person2 implements Person {
}

抽象类和接口区别

区别点抽象类接口
定义可以包含抽象方法的类主要是抽象方法和全局常量的集合
组成构造方法、抽象方法、普通方法、常量、变量常量、抽象方法(jdk8 以后,默认方法、静态方法)
使用子类继承抽象类(extends)子类实现接口(implements)
关系抽象类可以实现多个接口接口不能继承抽象类,但允许继承多个接口
常见设计模式模板方法简单工厂、工厂方法、代理模式
局限抽象类有单继承的局限接口没有此局限
选择如果抽象类和接口都能使用的话,优先使用接口,因为可以避免单继承的局限

Released under the MIT License.