接口定义

接口的内部主要就是封装了方法,包含抽象方法(JDK 7及以前),默认方法和静态方法(JDK 8),私有方法
(JDK 9),接口就是多个类的公共规范,接口是一种数据引用类型,其中重要内容是方法。

是使用 interface 关键字。它也会被编译成.class文件,但一定要明确它并
不是类,而是另外一种引用数据类型。(编译生成的字节码文件仍然是:.java -> .class

接口格式

public interface 接口名称 {
// 抽象方法
// 默认方法
// 静态方法
// 私有方法
// 常量
}

接口的使用步骤

1.接口不能直接使用,必须有一个“实现类”来“实现”该接口

//格式
public class 实现类名称 implements 接口名称{
    
}

2.接口的实现类必须覆盖重写(实现)接口中所有的抽象方法

实现:去掉abstract关键字,加上方法体大括号

3.创建实现类的对象进行使用

使用注意事项:

如果实现类没有覆盖重写接口中所有的抽象方法,那么这个实现类自己就必须是抽象类。

抽象方法的使用

//定义接口
public interface MyInterfaceAbstract {

    public abstract void method1();
    public abstract void method2();
    abstract void method3();
    void method4();

}

//定义实现类
public class MyInterfaceAbatratImpl implements MyInterfaceAbstract {
    @Override
    public void method1() {
        System.out.println("这是第一");
    }
    @Override
    public void method2() {
        System.out.println("这是第二");
    }
    @Override
    public void method3() {
        System.out.println("这是第三");
    }
    @Override
    public void method4() {
        System.out.println("这是第四");
    }
}

//定义测试类
public class Demo01Interface {

    public static void main(String[] args) {
        MyInterfaceAbatratImpl  impl=new MyInterfaceAbatratImpl();
        impl.method1();
        impl.method2();
    }

}
注意点:

1.接口中的抽象方法修饰符必须是两个字符:public abstract

2.这两个关键字修饰符,可以选择性省略(可以全省略)

3.方法三要素,可以随意定义

默认方法的使用

接口中的默认方法用于解决接口升级的问题(当接口已经定义好,且有一些类适用这个接口,为了不影响这些类的使用,所有使用默认方法在接口里添加)

//定义接口
public interface Live {
    public default void fly(){
        System.out.println("在天上飞");
    }
}

//定义实现类
public class Animal implements Live {
    //自动继承默认方法,什么都不用写,直接用
    //也可以在实现类里重写方法
}

//定义测试类
public class Test  {
    public static void main(String[] args) {
        Animal a=new Animal();
        a.fly();  //调用默认方法
    }

}
注意事项:
  1. 定义默认方法时的public可以省略
  2. 接口的默认方法可以通过接口实现类对象直接调用
  3. 接口的默认方法,可以被接口实现类进行重写

静态方法的使用

静态与.class 文件相关,只能使用接口名调用,不可以通过实现类的类名或者实现类的对象调用

正确调用方法:通过接口名称直接调用其中的静态方法

格式:接口名称.静态方法名

//定义接口
public interface Live {
    public static void run(){
        System.out.println("在地上跑");
    }
}

//定义实现类
public class Animal implements Live {
    //无法重写静态方法
}

//定义测试类
public class Text {
    public static void main(String[] args) {
//        Animal animal=new Animal();
//        animal.run():         【错误】:无法继承静态方法,也无法调用
        Live.run();
    }
}
注意事项:

1.定义静态方法时的public可以省略

2.不能通过接口实现类的对象来调用接口中的静态方法

私有方法的使用(JDK9以上)

如果一个接口中有多个默认方法,并且方法中有重复的内容,那么可以抽取出来,封装到私有方法中,供默认方法

去调用。从设计的角度讲,私有的方法是对默认方法和静态方法的辅助。这个

这个方法是不让实现类使用的,是私有化的。

普通私有方法

私有方法:只有默认方法可以调用。解决多个默认方法重复问题。

//格式
private 返回值类型 方法名称(参数列表){
    方法体
}


静态私有方法

私有静态方法:默认方法和静态方法可以调用。解决多个静态方法之间重复代码问题。

//格式
private static 返回值类型 方法名称(参数列表){
		方法体
}
public interface Live {
    default void func(){
        fun1();
        fun2();

    }
    private void fun1(){
        System.out.println("跑起来");
    }

    private void fun2(){
        System.out.println("跑起来");
    }
}

接口的常量的使用

接口当中也可以定义“成员变量”,但必须是使用 public、static、final 三个关键字进行修饰,从效果看,这就是接口的【常量】

格式:
public static final 数据类型 常量名称 = 数据值;
//public代表公共的,static表示与对象无关,final是指不可变
//常量名称需要是大写 多个单词的话需要用下划线分割
//定义接口
public interface Live {
    public static final int NUM_OF_MY=12;
}
//定义实现类
public class Number implements Live {

}
//定义测试类
public class Test {
    public static void main(String[] args) {
        System.out.println(Live.NUM_OF_MY);  //用接口来调用
//        Number number =new Number();
//        number.NUM_OF_MY;     【错误】:不能用实现类对象调用
    }
}
注意事项

1.接口中的常量,可以商量public static final

2.接口中的常量必须进行赋值,不能不赋值

3.接口当中的常量名称,使用完全大写的字母,用下划线进行分割

使用接口的注意事项

1.接口是没有静态代码和构造方法

2.一个类的直接父类是唯一的,但是一个类可以同时实现多个接口

class 类名 [extends 父类名] implements 接口名1,接口名2,接口名3... {
// 重写接口中抽象方法【必须】
// 重写接口中默认方法【不重名时可选】
}
//[ ]: 表示可选操作。

3.接口中,有多个抽象方法时,实现类必须重写所有抽象方法。如果抽象方法有重名的,只需要重写一次。

//第一个接口
public interface InterfaceA {
    public abstract void showA();
    public abstract void show();
}
//第二个接口
public interface InterfaceB {
    public abstract void showB();
    public abstract void show();
}
//实现类
public class C implements InterfaceA,InterfaceB {
    @Override
    public void showA() {

    }
    @Override
    public void showB() {

    }
    @Override
    public void show() {  //抽象方法有重名的,只需要重写一次

    }
}

4.如果实现类没有覆盖重写所有接口中的所有抽象方法,那么实现类就必须是个抽象类

5.接口中,有多个默认方法时,实现类都可继承使用。如果默认方法有重名的,必须重写一次。

//第一个接口
public interface InterfaceA {
    public default void methodA(){}
    public default void method(){}
}
//第二个接口
public interface InterfaceB {
    public default void methodB(){}
    public default void method(){}
}
//实现类
public class C implements InterfaceA,InterfaceB {
    @Override
    public void method() {

    }
}

6.优先级问题:当一个类,既继承一个父类,又实现若干个接口时,父类中的成员方法与接口中的默认方法重名,子类就近选择执行父类的成员方法。(继承优先于接口)

//定义接口
interface A {
public default void methodA(){
System.out.println("AAAAAAAAAAAA");
}
}
//定义父类
class D {
public void methodA(){
System.out.println("DDDDDDDDDDDD");
}
}
//定义子类
class C extends D implements A {
// 未重写methodA方法
}
//定义测试类
public class Test {
public static void main(String[] args) {
C c = new C();
c.methodA();
}
}
输出结果:
DDDDDDDDDDDD

接口的多继承

接口的继承使用 extends 关键字,子接口继承父接口的方法。

1.类与类之间是单继承的,直接父类只有一个

2.类与接口之间是多继承的,一个类可以实现多个接口

3.接口和接口之间是多继承的

//定义父接口
interface A {
	public default void method(){
	System.out.println("AAAAAAAAAAAAAAAAAAA");
	}
}
interface B {
	public default void method(){
	System.out.println("BBBBBBBBBBBBBBBBBBB");
	}
}
//定义子接口
interface D extends A,B{
	@Override
	public default void method() {
	System.out.println("DDDDDDDDDDDDDD");
	}
}

//子接口重写默认方法时,default关键字可以保留。
//子类重写默认方法时,default关键字不可以保留。
注意事项

1.如果父接口中的默认方法有重名的,那么子接口需要重写一次,而且带着default关键字

2.多个父接口当中的抽象方法重复也没有关系。