java之接口

2020-12-01

0x01.接口

什么是接口?
接口是Java语言中的一种引用类型,是方法的"集合",所以接口的内部主要就是定义方法,包含常量,抽象方法(JDK 7及以前),默认方法和静态方法(JDK 8),私有方法(jdk9)

接口的定义,它与定义类方式相似,但是使用 interface 关键字。它也会被编译成.class文件,但一定要明确它并不是类,而是另外一种引用数据类型。

public class 类名.java-->.class
public interface 接口名.java-->.class

引用数据类型:数组,类,接口。

接口的使用,它不能创建对象,但是可以被实现( implements ,类似于被继承)。一个实现接口的类(可以看做是接口的子类),需要实现接口中所有的抽象方法,创建该类对象,就可以调用方法了,否则它必须是一个抽象类。

实例:

public interface IA {
    // 常量 默认修饰符是 public static final 这3个修饰符可以省略不写
    public static final int NUM = 10;
    int NUM1 = 20;

    // 抽象方法 默认修饰符是 public abstract 这2个修饰符可以省略不写
    public abstract void method1();
    void method2();

    // 默认方法 默认修饰符是 public default public可以省略,default不可以省略
    public default void method3(){
        System.out.println("IA 接口默认方法");
    }

    // 静态方法 默认修饰符 public static public可以省略,static不可以省略
    public static void method4(){
        System.out.println("静态方法");
    }

    // 私有方法 修饰符 private   private不可以省略
    private void method5(){
        System.out.println("私有非静态方法");
    }

    private static void method6(){
        System.out.println("私有静态方法");
    }
}

public class Test {
    public static void main(String[] args) {
        /*
            接口的定义:
                public interface 接口名{
                     jdk7及其以前:  常量,抽象方法
                     jdk8: 额外增加默认方法和静态方法
                     jdk9及其以上: 额外增加了私有方法
                }
         */
        System.out.println(IA.NUM1);// 10
    }

    // 类中的默认方法,使用默认权限修饰符(空)
    void method(){

    }
}

实现概述

类与接口的关系为实现关系,即类实现接口,该类可以称为接口的实现类,也可以称为接口的子类。实现的动作类似继承,格式相仿,只是关键字不同,实现使用 implements关键字。

实现格式
  • 类可以实现一个接口,也可以同时实现多个接口。

  • 类实现接口后,必须重写接口中所有的抽象方法,否则该类必须是一个“抽象类”。

public interface IA{
    public void show1();
}
public interface IB{
    public void show2();
}
public class Zi implements IA ,IB{
    public void show1(){
    }
    public void show2(){
    }
}
  • 类可以在“继承一个类”的同时,实现一个、多个接口;
public class Fu{}
public interface IA{}
public interface IB{}
public class Zi extends Fu implements IA,IB{//一定要先继承,后实现
}

接口中成员访问特点概述

  接口中成员的访问特点:
                接口中的常量: 主要是供接口直接使用
                接口中的抽象方法: 供实现类重写的
                接口中的默认方法: 供实现类继承的(实现类中可以直接调用,实现类对象也可以直接调用)
                接口中的静态方法: 只供接口直接调用,实现类继承不了
                接口中的私有方法: 只能在接口中直接调用,实现类继承不了
案例演示
/*
接口
*/
public interface IA {
    //  接口中的常量: 主要是供接口直接使用
    public static final int NUM = 10;

    // 接口中的抽象方法: 供实现类重写的
    public abstract void method1();

    // 接口中的默认方法: 供实现类继承使用(实现类中可以直接调用,实现类对象也可以直接调用)
    public default void method2(){
        System.out.println("默认方法method2");
        method4();
        method5();
    }

    // 接口中的静态方法: 只供接口直接调用,实现类继承不了
    public static void method3(){
        System.out.println("静态方法method3");
        method5();
    }

    // 接口中的私有方法: 只能在接口中直接调用,实现类继承不了
    private void method4(){// 只能在接口的默认方法中调用
        // 方法体
        method5();
    }

    private static void method5(){//
        // 方法体
    }
}

实现类:

public class ImpA implements IA{

   /* @Override
    public void method2() {

    }*/

    @Override
    public void method1() {
        System.out.println("重写接口中的method1抽象方法");
    }
}

测试类:

public class Test {
    public static void main(String[] args) {
        /*
            接口中成员的访问特点:
                接口中的常量: 主要是供接口直接使用
                接口中的抽象方法: 供实现类重写的
                接口中的默认方法: 供实现类继承的(实现类中可以直接调用,实现类对象也可以直接调用)
                接口中的静态方法: 只供接口直接调用,实现类继承不了
                接口中的私有方法: 只能在接口中直接调用,实现类继承不了
         */
        System.out.println(IA.NUM);// 10

        // 创建实现类对象,访问NUM常量
        ImpA ia = new ImpA();
        System.out.println(ia.NUM);// 10

        // 调用method2方法
        ia.method2();

        // 通过接口名调用接口中的静态方法
        IA.method3();
        //ia.method3();// 编译报错,
    }
}

接口和接口的关系

  • 公有静态常量的冲突
  • 公有抽象方法的冲突
  • 公有默认方法的冲突
  • 公有静态方法的冲突
  • 私有方法的冲突

讲解

公有静态常量的冲突
  • 实现类不继承冲突的变量
interface IA{
    public static final int a = 10;
    public static final int b= 20;
}
interface IB{
    public static final int a = 30;
}
class Zi implements IA,IB{
    //只继承了b,没有继承a,因为a冲突了
}

public class Demo {
    public static void main(String[] args) {
        Zi z = new Zi();
     //   System.out.println(z.a);//编译错误
        System.out.println(z.b);
    }
}

公有抽象方法的冲突
  • 实现类只需要重写一个
interface IA{
    public void show();
}
interface IB{
    public void show();
}
class Zi implements IA,IB{
    @Override
    public void show() {//子类只需要重写一个show()即可
        System.out.println("子类的show()...");
    }
}
public class Demo {
    public static void main(String[] args) {
        Zi z = new Zi();
        z.show();
    }
}
公有默认方法的冲突
  • 实现类必须重写一次最终版本
interface IA{
    public default void show(){
        System.out.println("IA");
    }
}
interface IB{
    public default void show(){
        System.out.println("IB");
    }
}
class Zi implements IA,IB{
    @Override
    public void show() {//必须重写一次的show()
        System.out.println("Zi的show()....");
    }
}
public class Demo {
    public static void main(String[] args) {
        Zi z = new Zi();
        z.show();
    }
}

公有静态方法的冲突
  • 静态方法是直接属于接口的,不能被继承,所以不存在冲突

    interface IA{
        public static  void show(){
            System.out.println("IA");
        }
    }
    interface IB{
        public static void show(){
            System.out.println("IB");
        }
    }
    class Zi implements IA,IB{
    
    }
    public class Demo {
        public static void main(String[] args) {
            Zi z = new Zi();
            z.show();//编译错误,show()不能被继承。
        }
    }
    
    
    
私有方法的冲突
  • 私有方法只能在本接口中直接使用,不存在冲突

接口与接口之间的关系

  • 接口多继承时的冲突情况
    • 公有静态常量的冲突
    • 公有抽象方法的冲突
    • 公有默认方法的冲突
    • 公有静态方法和私有方法的冲突

讲解

接口与接口之间的关系
  • 接口可以“继承”自另一个“接口”,而且可以“多继承”。

    interface IA{}
    interface IB{}
    interface IC extends IA,IB{//是“继承”,而且可以“多继承”
    }
    
接口继承接口的冲突情况
公有静态常量的冲突
interface IA{
    public static final int a = 10;
    public static final int b = 30;
}
interface IB{
    public static final int a = 20;
}
interface IC extends IA,IB{//没有继承a
}
//测试:
main(){
    System.out.println(IC.a);//错误的
}
公有抽象方法冲突
interface IA{
    public void show();
}
interface IB{
    public void show();
}
interface IC extends IA,IB{//IC只继承了一个show()
}
class Zi implements IC{
    //重写一次show()
    public void show(){
    }
}
公有默认方法的冲突
interface IA{
    public default void d1(){
    }
}
interface IB{
    public default void d1(){
    }
}
interface IC extends IA,IB{//必须重写一次d1()
    public default  void d1(){
    }
}
公有静态方法和私有方法
  • 不冲突,因为静态方法是直接属于接口的,只能使用接口直接访问,而私有方法只能在接口中访问,也没有冲突

实现类继承父类又实现接口时的冲突

  • 公有静态常量的冲突
  • 公有抽象方法的冲突
  • 公有默认方法的冲突
  • 公有静态方法
  • 私有方法的冲突

讲解

父类和接口的公有静态常量的冲突
class Fu{
    public static final int a = 10;
}
interface IA{
    public static final int a = 20;
}
class Zi extends Fu implements IA{//没有继承a变量
}
public class Demo {
    public static void main(String[] args) {
        System.out.println(Zi.a);//编译错误
    }
}

父类和接口的抽象方法冲突
abstract class Fu{
    public abstract void show();
}
interface IA{
    public void show();
}
class Zi extends Fu implements IA{// 必须重写
    
}
//测试:
main(){
    Zi z = new Zi();
    z.show();//a
}

父类和接口的公有默认方法的冲突
class Fu{
    public void show(){
        System.out.println("a");
    }
}
interface IA{
    public default void show(){
        System.out.println("b");
    }
}
class Zi extends Fu implements IA{
}
//测试:
main(){
    Zi z = new Zi();
    z.show();//a
}

父类和接口的公有静态方法
class Fu{
    public static void show(){
        System.out.println("fu...");
    }
}
interface IA{
    public static void show(){
        System.out.println("IA...");
    }
}
class Zi extends Fu implements IA{//只继承了"父类"的静态方法,没有继承接口的静态方法

}
public class Demo {
    public static void main(String[] args) {
        Zi.show();//fu…
    }
}

父类和接口的私有方法
  • 不存在冲突

实操--抽象类和接口的练习

需求:

通过实例进行分析和代码演示抽象类和接口的用法。

1、举例:

​ 犬: --->父类 抽象类

​ 行为:吼叫;吃饭; ----- 抽象类

​ 缉毒犬: ---> 继承犬类

​ 行为:吼叫;吃饭;缉毒;

​ 缉毒接口:

​ 缉毒的功能(抽象方法)

  • 如果所有子类都有的功能: 通用功能(非抽象方法),非通用功能(抽象方法),定义到父类中
  • 如果某个功能是一个类额外增加的,那么就可以把这个额外的功能定义到接口中,再这个类去实现

分析:

​ 由于犬分为很多种类,他们吼叫和吃饭的方式不一样,在描述的时候不能具体化,也就是吼叫和吃饭的行为不能明确。当描述行为时,行为的具体动作不能明确,这时,可以将这个行为写为抽象行为,那么这个类也就是抽象类。

​ 可是有的犬还有其他额外功能,而这个功能并不在这个事物的体系中 , 例如 : 缉毒犬。缉毒的这个功能有好多种动物都有 , 例如 : 缉毒猪 , 缉毒鼠。我们可以将这个额外功能定义接口中 ,让缉毒犬继承犬且实现缉毒接口 , 这样缉毒犬既具备犬科自身特点也有缉毒功能。

  • 额外的功能---> 在接口中定义,让实现类实现
  • 共性的功能---> 在父类中定义,让子类继承

实现:

//定义缉毒接口 缉毒的词组(anti-Narcotics)比较长,在此使用拼音替代
interface JiDu{
    //缉毒
	public abstract void jiDu();
}
//定义犬科,存放共性功能
abstract class Dog{
    //吃饭
	public abstract void eat();
    //吼叫
	public abstract void roar();
}
//缉毒犬属于犬科一种,让其继承犬科,获取的犬科的特性,
//由于缉毒犬具有缉毒功能,那么它只要实现缉毒接口即可,这样即保证缉毒犬具备犬科的特性,也拥有了缉毒的功能
class JiDuQuan extends Dog implements JiDu{
	public void jiDu() {
	}
	void eat() {
	}
	void roar() {
	}
}

//缉毒猪
class JiDuZhu implements JiDu{
	public void jiDu() {
	}
}

小结:

  • 额外的功能---> 在接口中定义,让实现类实现
    • 如果可以确定的通用功能,使用默认方法
    • 如果不能确定的功能,使用抽象方法
  • 共性的功能---> 在父类中定义,让子类继承
    • 如果可以确定的通用功能,使用默认方法
    • 如果不能确定的功能,使用抽象方法