Java interface 的进化

core-java
标签: #<Tag:0x00007f1d27f380e0>

#1

Java 8 之前的接口

目前, 大部分人对 interface 的认识还停留在 java7这个版本, 也就是说interface 只能有:

  • public method的声明
  • 常量
public interface MyInterface2 {
    String s = "hello world.";
    //其中 String s 并没有加 public, final 和 static, 因为它默认就是 public static final的. 
    //如果给他加一个 protected 或 private 会报错.  

    void method(); //method()方法也一样, 默认 public.
}

这样的接口功能非常的单一. 并且因为有 abstract class 的存在, 我个人一直认为 interface 的存在有些多余. 只有在大型框架的设计上才会发挥它真正的作用, 平时的开发中极少用到.

Java 8 中终于增强了接口.

Java8中加入了

  • static method 静态方法
  • default method 默认方法

静态方法

语法是这样的:

public interface MyInterface {
    static void staticMethod() {
        System.out.println(" static method ");
    }
}

static method 我非常的喜欢. 不知道大家有没有这种经验, 为了不把一些非业务逻辑的功能性方法和处理业务逻辑的方法混在一个类里, 我们经常需要一个 help 类或utils类. 现在我们可以把这些方法写在interface 的 static method 里了, 整个项目会变得清爽很多.

默认方法

语法:

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

语法很简单. 现在 interface 里不仅可以有方法的声明,也可以与方法的实现了.

为什么要有默认方法呢? 官方的解释的比较模糊, 我的理解大概是这样, 假如你已经发布了一些接口, 有很多其他的工程都在用, 之后呢, 如果你想要在这个接口里增加一些新的方法, 这时就比较尴尬了, 因为其他工程中使用了这个接口的地方就全都会报错, 因为接口中定义的方法声明, 实现类必须全都实现. 所以你只能加个新的接口, 把这些新方法加进新接口里, 这种解决方案有时会把工程搞得很混乱. 会出现一大堆功能都差不多的接口和实现类.

默认方法可以在很大程度上解决这个问题. 因为默认方法不是强制需要实现的.

静态方法和默认方法的出现还有一个原因就是为了 lambda. 这里就不详细展开, 以后为会详细接受 Lambda.

关于静态方法和默认方法 一些要注意的知识点:

  1. 静态方法,只能通过接口名调用,不可以通过实现类的类名或者实现类的实例调用。默认方法,只能通过接口实现类的对象来调用。

  2. java 里是可以同时实现多个接口的. 如果两个接口里有同样的default 方法声明, 这种情况会报错, 无法编译. 但是如果在类里override 了这个方法, 就不会报错了.

  3. 如果一个 class extend 了一个类, 又 implement 了一个接口. 可是父类中的方法和接口中的 default 方法声明相同, 这种情况里, 父类中的方法会覆盖接口中的 default 方法. 接口中的方法会被忽略. 不会报错

  4. 还有一点, 因为 interface里的所有方法都是 public 的, 所以 default 方法也是 public 的, 并且只能是 public 的.

  5. 实现类里可以有和接口中的静态方法重名的方法, 但是不会覆盖它. 因为静态方法只能用类名调用, 实现类中的方法用实现类的类名调用, 所以并不冲突. 所以也说明接口中的静态方法不会被继承.

Java 9 接口被进一步完善.

Java 9 中新增了:

  • private method 私有方法
  • private static method 私有静态方法

语法

public interface MyInterface {
    private void method1 () {
    }
    private static void method2() {
    }
}

Java 8 中增加了方法的实现, 可是并没有 private 方法, 这其实是很不方便的, 加入我想写一个比较复杂的静态方法, 或者默认方法时, 想把一些逻辑分到其他的方法里, 但是interface 又不支持 private 方法, 所以我的一些仅在内部用的逻辑也要暴露给所有人. 这个是不合理的.

所以我觉得 java 9 的这些特性, 其实是在完善 java 8的默认方法和静态方法. 私有方法可以支持默认方法, 私有静态方法可以支持静态方法.

最后总结一下接口中的前缀

  • public — 就是 java8之前版本里的方法, 最基本的方法声明, 这个 public关键字可以省略
  • static — java8新特性, 静态方法
  • public static — 与 static 方法相同, 这个 public关键字可以省略
  • public abstract - 就是 java8之前版本里的方法, 最基本的方法声明,public 和 abstract 关键字可以省略
  • default — java8新特性. 默认方法.
  • public default - 与 default 方法相同, 这个 public关键字可以省略
  • private static - java9中的新特性
  • private abstract - 不支持, 因为 private 是不能被继承的, 但是abstract方法必须在子类中实现, 所以这个两个关键字是冲突的.
  • private default - 不支持, 编译报错. 其实default方法算半个 private 方法, 因为不能被继承. 但可以在外部方法
  • private - java9中的新特性