栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Java基础 | 接口(Interface)

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Java基础 | 接口(Interface)

1.概念

    在Java程序设计语言中,接口不是类,而是对希望符合这个接口的类的一组需求(类似于抽象类,皆为抽象内容,却又区别于抽象类)。由于Java不支持多重继承特性,每个类只能扩展一个类,但可以实现多个接口。实际上,接口可以提供多重继承的大多数好处,同时还能避免多重继承的复杂性和低效性。

2.属性
  • 接口不是类,具体来说,不能使用 new 运算符实例化一个接口。
    InterfaceName aInterface = new InterfaceName() // Error

  • 尽管不能构造接口的对象,却能声明接口的变量。接口变量必须引用实现implements了该接口的类对象。
    class ClassName implements InterfaceName {…}
    InterfaceName aClass = new ClassName();

  • 如同使用 instanceof 检查一个对象是否属于某个特定类一样,也可以使用 instanceof 检查一个对象是否实现类某个特定的接口。
    anObject instanceof InterfaceName

  • 与建立类的继承层次一样,也可以扩展extends接口层次。允许存在多条接口链,从通用性较高的接口扩展到专用性较高的接口。接口不同于类,可以实现多重继承。
    interface InterfaceName1 extends InterfaceName {…}
    interface InterfaceName2 extends InterfaceName {…}
    interface InterfaceName3 extends InterfaceName1, InterfaceName2 {…}
    … …

  • 虽然在接口中不能包含实例字段,但是可以包含常量。与接口中的方法自动被设置为public abstract一样,接口中的字段总是public static final。(Java语言规范建议不要提供多余的关键字,即无需修饰)

  • 静态方法:在Java 8中,允许在接口中定义静态static方法。理论上讲,没有任何理由认为这是不合法的,只是这有违于将接口作为抽象规范的初衷。目前为止,通常的做法都是将静态方法放在伴随类中。在标准库中,你会看到成对出现的接口和实用工具类, 如Collection/Collections 或Path/Paths。

  • 私有方法:在Java 9中,接口中的方法可以是private。private方法可以是静态方法或实例方法。由于私有方法只能在接口本身的方法中使用,所以它们的用法很有限,只能作为接口中其他方法的辅助方法。

  • 默认方法:在Java 8之前,接口中的方法都是抽象的,不允许有方法体。在此之后可以为接口方法提供一个默认实现,必须用default修饰符标记这样一个方法。默认方法可以调用其他方法。

    • 解决默认方法冲突问题:
    1. 超类优先。如果超类提供了一个具体方法,同名而且有相同参数类型的默认方法会被忽略。
    2. 接口冲突。如果一个接口提供了一个默认方法,另一个接口提供了一个同名而且参数类型相同的方法(不管是否为默认方法),必须覆盖这个方法来解决冲突。
    • 情形一:会继承接口中多个签名相同、实现不同的默认方法。类必须重写该方法,以解决二义性问题。
      class ClassName implements InterfaceName1, InterfaceName2 {
          @Override
          public String getInterfaceName() { return " InterfaceName1 + InterfaceName2"; }
          …
      }
      interface InterfaceName1 {
          default String getInterfaceName() { return " InterfaceName1"; }
          …
      }
      interface InterfaceName2 {
          default String getInterfaceName() { return " InterfaceName2"; }
          …
      }
    • 情形二:会继承接口中多个签名相同的默认方法与抽象方法。类必须重写该方法,以解决二义性问题。
      class ClassName implements InterfaceName1, InterfaceName2 {
          @Override
          public String getInterfaceName() { return " InterfaceName1 + InterfaceName2"; }
          …
      }
      interface InterfaceName1 {
          default String getInterfaceName() { return " InterfaceName1";}
          …
      }
      interface InterfaceName2 {
          String getInterfaceName();
          …
      }
    • 情况三:存在多个签名相同的(非默认)方法(与Java 8之前情形一样,不存在冲突)。两种选择:①类实现该方法;②不实现该方法,作为抽象类。
      ①class ClassName implements InterfaceName1, InterfaceName2 {
          @Override
          public String getInterfaceName() { return " InterfaceName1 + InterfaceName2"; }
          …
      }

      ②abstract class ClassName implements InterfaceName1, InterfaceName2 {
          abstract public String getInterfaceName() // 可有可无
          …
      }
      interface InterfaceName1 {
          String getInterfaceName();
          …
      }
      interface InterfaceName2 {
          String getInterfaceName();
          …
      }
    • 情况四:扩展了超类,同时实现了接口,会继承多个签名相同的方法。此时,子类只会考虑超类的具体方法,接口的默认方法都会被忽略。
      class ClassName extends SuperClassName implements InterfaceName {
          //getInterfaceName()方法不存在问题,只会继承超类该方法。
          …
      }
      class SuperClassName {
          public String getInterfaceName() { return " null"; }
          …
      }
      interface InterfaceName {
          default String getInterfaceName() { return " InterfaceName";}
          …
      }
3.函数式接口
  • 对于有且仅有一个抽象方法的接口,称为函数式接口(functional interface,其注解为@FunctionalInterface)
  • 为什么函数式接口只有一个抽象方法,接口中的所有方法不应该都是抽象的吗?
    通过查看注解@FunctionalInterface的 javac 注释,或许能找到答案:
    ①由于默认方法和静态方法具有实现,因此它们不再是抽象方法范畴。
    ②如果接口声明了一个覆盖 java.lang.Object 的公共方法之一的抽象方法,这也不会计入接口的抽象方法计数,因为接口的任何实现都将具有来自 java.lang.Object 或其他地方的实现
4.java.util.function包

    在Java 8中新增加的 java.util.function 包内置了四大核心函数式接口(Consumer消费型、Function函数型、Predicate断言型和Supplier供给型)及其派生函数式接口。

4.1 Consumer消费型
@FunctionalInterface
public interface Consumer {

    
    void accept(T t);
}
4.2 Function函数型
@FunctionalInterface
public interface Function {

    
    R apply(T t);
}
4.3 Predicate断言型
@FunctionalInterface
public interface Predicate {

    
    boolean test(T t);
}
4.4 Supplier供给型
@FunctionalInterface
public interface Supplier {

    
    T get();
}
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/601491.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号