开发声明、实现和/或继承接口的代码,并使用 @Override注解

接口

  • 与类一样,接口具有public或default的可访问性
  • 接口中声明的字段默认为 PUBLIC、 STATIC 和 FINAL。与方法一样,即使您没有指定它们,编译器也会这样对待它们。即默认字段都为静态常量
    image.png
    所以接口中的成员变量不能未private,且必须要初始化赋值
  • 接口可以extends任意数量的接口

为什么接口可以多实现,类只能单继承

如果你可以从多个类继承,当方法签名相同时,无法选择具体是哪个父类的方法,但接口因为只是定义,实现类是要重写父类方法的,避免了该问题

  • 方法只有返回类型不同时,由于返回类型在方法的签名中没有被考虑,Java 编译器会生成一个错误:
interface Truck {
    void accelerate();
}
interface CompactCar {
    int accelerate();
}
class Car implements Truck, CompactCar {
    // Java will complain about duplicate methods
    // and incompatible return types
    public void accelerate() {
        // implementation
    }
    public int accelerate() {
        // implementation
    }
}

image.png
顺带提一句重载是可以改变方法的返回类型的

@override注解

为什么要加这个注解,因为的方法没有正确重写或实现该方法,编译器将生成错误。这是这个注解的的唯一功能。这在一些情况下很有用,比如一个输入错误导致了一个不太明显的错误:

interface CompactCar {
    int accelerate();
}
class Car implements CompactCar {
    // Compiler will mark an error about method
    // "acelerate" not overriding or implementing something
    @Override
    public int acelerate() {
        // implementation
    }
}

JDK8接口新功能

java8提供了默认的方法,我们不必为它们提供实现,因为它们是非抽象的方法。允许使用带有方法体的方法

  • 原因
    如果一个接口被数百个类实现,现在要修改该接口,增加一个方法
    1.数百个实现类必须都要增加实现否则编译报错,量大
    2.某些原因无法更新或访问实现类代码
    3.在功能上新增加的方法对于某些实现类来说并不需要,即不需要手动重写

默认Default方法

将默认方法添加到接口的主要原因是为了支持接口演进,为接口添加新功能,同时确保与为旧版本编写的代码兼容。

  • 与抽象类的区别
    1.抽象类单继承,接口可多实现
    2.抽象类有实例字段具有状态属性,接口不可以

定义默认方法

interface Processable {
    void processInSequence();
    default void processInParallel() {
        /** Default implementation goes here */
    }
}
  • 默认方法是public的,就像接口的其他方法一样
  • 默认方法不能是final的。接口中所有方法都不能为final
  • 默认方法无法被synchronized加锁,应该在实现类中实现
    image.png
    image.png
  • 不能为Object类方法提供默认方法
    如果接口具有带有这些签名的方法,编译器将抛出错误。原因是这些方法都是关于对象的状态。因为接口没有状态,所以这些方法应该在实现类中
boolean equals(Object o)
int hashCode()
String toString()

image.png

重写默认default方法

方法定义使用上,类的优先级高于接口,如果一个类重写了default的方法,那么类方法就是使用的方法。就和其他只是定义了方法签名的没有方法体的方法一样

  • 即使该类将默认方法重新定义为 abstract,这也是正确的
interface Processable {
    void processInSequence();
    default void processInParallel() {
        System.out.println("Default parallel");
    }
}
// Class Task has to be abstract
abstract class Task implements Processable {
    @Override
    public void processInSequence() {
        System.out.println("Processing in sequence");
    }
    @Override
    public abstract void processInParallel();
}
  • 调用方法的默认实现,可以使用接口的名称,后面跟着关键字 super
public void processInParallel() {
    Processable.super.processInParallel();
}
  • 当一个类的继承实例方法覆盖了默认的接口方法,则使用的也是继承的实例类重写的方法
interface Processable {
    default void processInParallel() {
        System.out.println("Default parallel");
    }
}
class Process {
    public void processInParallel() {
        System.out.println("Class parallel");
    }
}
public class Task
        extends Process implements Processable {
    public static void main(String args[]) {
        Task t = new Task();
        t.processInParallel(); //Class parallel
    }
}

具有默认deafult方法的多个接口继承

两个接口具有相同的默认方法被子类实现时,如果子类不覆盖该默认方法则会编译报错

编译器不知道选择哪个,所以它会生成一个错误。在这种情况下,Task 必须提供一个实现(遵循前面的规则,即更具体的接口(或类)总是会胜过不那么具体的接口)来覆盖接口缺省方法并解决问题:

interface Parallelizable1 {
    default void processInParallel() {
        System.out.println("Parallelizable parallel");
    }
}
public class Task
        implements Processable1, Parallelizable1 {
    @Override
    public void processInSequence() {
        System.out.println("Processing in sequence");
    }
    public static void main(String args[]) {
        Task t = new Task();
        t.processInParallel();
    }
}

报错,必须要重写该默认方法
image.png

接口的静态方法

1.默认为public
2.不能被继承,但是类的静态方法可以被继承
3.使用时必须在方法前面加上接口名,因为接口不能被实例化


这个家伙很懒,啥也没有留下😋