类的扩展(一):接口的本质

  1. 接口的本质是什么?
    答:接口是一种能力,很多时候反映的是对象以及对对象操作的本质

  2. 定义接口的格式?
    答:

    • interface 这个关键字声明接口,修饰符一般都是 public
    • 没有定义方法体,Java 8 之前,接口内不能实现方法
    • 接口方法不需要加修饰符,加与不加都相当于 public abstract
    • 定义一个接口本身并没有做什么,也没有太大的用处,它还需要至少两个参与者:一个需要实现接口,另一个使用接口
    • 类可以实现接口,表示类的对象具有接口所表示的能力。
  3. 使用接口的格式?
    答:

    • 接口不能 new,不能直接创建一个接口对象,对象只能通过类来创建
    • 可以声明接口类型的变量,引用实现了接口的类对象
  4. 针对接口编程的好处是?
    答:代码复用,降低耦合,提高灵活性。

  5. 接口的几个小细节?
    答:

    • 接口中的变量。接口中可以定义变量,修饰符是 public static final,但这个修饰符是可选的,即使不写,也是 public static final,通过接口名.变量名访问变量。
    • 接口的继承。接口也可以继承,和类一样的是,关键字也是 extends;和类不同的是,接口可以有多个父接口,即 public interface IChild extends IBase1, IBase2 {} 的写法是合法的。
    • 类的继承与接口。类的继承与接口可以共存,需要注意的是关键字 extends 要放在 implements 之前。
    • instanceof。与类一样,接口也可以使用 instanceof 关键字,用来判断一个对象是否实现了某接口
  6. 怎么理解使用组合和接口替代继承?
    答:

    • 继承至少有两个好处:一个是复用代码;另一个是利用多态和动态绑定统一处理多种不同子类的对象。
    • 使用组合替代继承,可以复用代码,但不能统一处理。
    • 使用接口替代继承,针对接口编程,可以实现统一处理不同类型的对象,但接口没有代码实现,无法复用代码。
    • 将组合和接口结合起来替代继承,就既可以统一处理,又可以复用代码了。
  7. Java 8 和 Java 9 对接口做了哪些增强?
    答:

    • 在 Java 8 之前,接口中的方法都是抽象方法,都没有实现体
    • Java 8 允许在接口中定义两类新方法:静态方法和默认方法,它们有实现体
    • 示例:

      1
      2
      3
      4
      5
      6
      7
      8
      9
      public interface IDemo {
      void hello();
      public static void test() {
      System.out.println("hello");
      }
      default void hi() {
      System.out.println("hi");
      }
      }
    • 静态方法 test() 可以通过 IDemo.test() 调用。
      * 默认方法用关键字 default 修饰。默认方法有默认的实现,实现类可以改变它的默认实现,也可以不改变

    • 在 Java 8 中,静态方法和默认方法都必须是 public 的,Java 9 去除了这个限制,它们都可以是 private,引入 private 方法主要是为了方便多个静态或默认方法复用代码。
  8. Java 8 引入默认方法的原因是?
    答:

    • 引入默认方法主要是函数式数据处理的需求,是为了便于给接口增加功能
    • 在没有默认方法之前,Java 是很难给接口增加功能的。比如 List 接口,因为有太多非 Java JDK 控制的代码实现了该接口,如果给接口增加一个方法,则那些接口的实现就无法在新版 Java 上运行,必须改写代码实现新的方法,这显然是无法接受的。
    • 函数式数据处理需要给一些接口增加一些新的方法,所以就有了默认方法的概念,接口增加了新方法,而接口现有的实现类也不需要必须实现。
  9. 接口增加默认方法的示例?
    答:

    • List 接口增加了 sort 默认方法,定义为:

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      default void sort(Comparator<? super E> c) {
      Object[] a = this.toArray();
      Arrays.sort(a, (Comparator) c);
      ListIterator<E> i = this.listIterator();
      for(Object e : a) {
      i.next();
      i.set((E) e);
      }

      }
    • Collection 接口增加了 stream 默认方法,其定义为:

      1
      2
      3
      default Stream<E> stream() {
      return StreamSupport.stream(spliterator(), false);
      }