接口的详细介绍

接口是一个抽象类型,包含抽象方法和常量。默认方法允许接口提供实现,避免接口升级导致实现类需要修改。当接口冲突时,父类方法优先。类可以通过实现多个接口实现多继承。接口在实际应用中,如Comparator,可用于自定义排序规则。
摘要由CSDN通过智能技术生成

接口概念

接口 是一个抽象类型,是抽象方法的集合,以关键字 interface 来声明。一个类通过实现 (implements) 接口的方式,来实现接口的抽象方法。因此,接口可以理解为,对类定义进行了统一的格式规范

接口的组成部分

抽象方法

抽象方法,就是只有方法声明,而没有具体的方法实现。
接口中的抽象方法会隐式指定为 public abstract,即接口内void test();等价于public abstract void test(); 并且也只可指定为 public abstract,指定其他修饰符会报错。

常量

接口中的字段(field)会被自动设置为 public static final,即静态常量。通过 接口.常量名 即可调用。字段指定为其他修饰符会报错。

默认方法

可以为接口方法提供一个默认实现,用 default 修饰符标记方法即可。

public interface Test {
    
    default void test() {
        System.out.println("这是一个默认方法");
    }
    
}

默认方法的作用

  1. 提供方法的默认实现:实现接口时,只需要实现关注的方法即可(实现类的方法实现会覆盖接口方法的默认实现),不关注的方法不用实现,因为有默认实现。
  2. 接口演化:以 Collection 接口为例,这个接口作为 Java 的一部分已经有很多年了;在 Java 8 中,又为这个接口增加了一个 stream 方法。如果 stream 不是默认方法,那么接口增加 stream 方法后,所有实现类都要作修改;使用默认方法就可以解决这个问题,接口增加 stream 方法后,实现类也不会受到影响。

解决默认方法冲突

一个类继承了另一个类(父类),并同时实现了多个接口;这些接口有相同的默认方法(同名且有相同参数类型),父类中也有 同名且有相同参数类型 的具体方法。这个时候就会造成冲突,Java 中解决这种冲突的规则如下:

  1. 父类优先。如果父类提供了一个具体方法,接口中 同名且有相同参数类型 的默认方法会被忽略。
  2. 接口冲突。如果只是多个接口有相同的默认方法,父类没有 同名且有相同参数类型 的具体方法,那么必须在 接口实现类 中重写方法覆盖掉默认方法,在重写方法中可以使用 接口名.super.方法名 调用指定接口的默认方法。
public class MyClass implements A, B {

    @Override
    public void hello(int i) {
        A.super.hello(i);
        System.out.println("MyClass");
    }

}

public interface A {

    default void hello(int a) {
        System.out.println("default A");
    }

}

public interface B {

    default void hello(int b) {
        System.out.println("default B");
    }

}

静态方法

接口中可以声明静态方法(有具体实现);使用 接口名.方法名 即可调用。

public interface A {

    static void hi() {
        System.out.println("hi");
    }

}

接口与抽象类

在学习接口的时候是否有这样的疑惑,接口无非就是定义抽象方法,类实现接口来实现这些抽象方法;这个抽象类也能做,即抽象类定义抽象方法,类继承抽象类实现其中的抽象方法。这样接口是否显得很多余,似乎有抽象类就够了?
其实不然,因为存在这么一个问题:类的单继承机制,一个类继承一个抽象类后,就无法继承其他抽象类;而一个类可以实现多个接口,因此接口能够提供多继承的许多好处。

接口的特性

  1. 类不允许多继承,接口允许多继承,一个接口可以继承多个其他接口。
  2. 一个类只能继承一个类,但是能实现多个接口
  3. 接口不能实例化,却能声明接口的变量,接口变量可以引用实现了接口的类对象。
  4. 实现接口时,抽象类可以不用实现所有的抽象方法,非抽象类必须实现所有的抽象方法。
  5. 接口中的所有方法自动地属于 public。因此,在接口中声明方法时,不必提供关键字 public。
  6. 默认方法可以调用接口中的任何其他方法,包括 抽象方法、默认方法、静态方法。
  7. 默认方法仍然是成员方法,需要通过对象(接口实现类的实例)调用,而不是如静态方法一般 直接通过接口调用。

接口的应用实例

Arrays 中有 sort 方法,可以对 对象数组进行排序;sort 有以下重载版本,可以传入 Comparator(比较器)自定义排序规则。
public static <T> void sort(T[] a, Comparator<? super T> c)
现定义如下类实现 Comparator<String> 接口,使得字符串按照长度大小进行比较。

public class LengthComparator implements Comparator<String> {
    @Override
    public int compare(String o1, String o2) {
        return o1.length() - o2.length();
    }
}

当调用 sort 方法时,传入 LengthComparator 对象,即可实现字符串数组 按照长度由小到大进行排序。

public static void main(String[] args) {
    String[] strs = {"bbbbb", "aa", "fff"};
    Arrays.sort(strs, new LengthComparator());
    for (String s : strs) {
        System.out.println(s);
    }
}

执行结果
aa
fff
bbbbb

当然,可以使用 lambda 表达式对代码进行简化,这样就不需要写一个类去实现 Comparator 接口了。
Arrays.sort(strs, (s1, s2) -> s1.length() - s2.length());


如果有帮助的话,可以点个赞支持一下嘛🙏

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值