接口

接口

接口概述

为了解决抽象类单继承的局限,Java提供了接口。如果一个类只是由抽象方法和全局常量组成的,那么在这种情况下不会将其定义为一个抽象类,而只会定义为接口。接口就是一种公共规范标准,只要符合规范,大家都可以通用。

接口的使用原则

  • 接口必须有子类,但是一个子类可以实现多个接口。(如果子类实现的多个接口中有重名的方法会报错)
  • 接口的子类必须重写接口中所有的抽象方法。(如果不想重写全部抽象方法,就定义成抽象类)
  • 接口不能实例化(接口没有构造方法),可以利用实现类对象的向上转型进行实例化操作。
interface A{
    public static final String MSG = "HelloWorld!";
    public abstract void print();
}

对接口而言,其组成部分就是抽象方法和全局常量,所以很多人为了省事不写public abstract和public static final。上式等价于:

interface A{
    String MSG = "HelloWorld!";
    void print();
}

即使在接口的方法中没有写上public,其最终的访问权限也是public而不是default,覆写接口方法的子类方法的权限不能低于接口的权限,所以子类的方法必须加上public。既然如此,建议在接口中也写上public以防权限出错。
如果一个类既要继承抽象类又要实现接口,那么应该采用先继承后实现接口的顺序完成。一个抽象类可以继承一个抽象类或实现若干个接口,但是一个接口却不能继承抽象类。不过一个接口可以使用extends同时继承多个父接口。

interface A{	//父接口
    public abstract void funA();
}
interface B{	//父接口
    public abstract void funB();
}
interface C extends A,B{	//接口多继承
    public void funC();
}
class X implements C{	//实现C接口要覆写全部抽象方法
    public void funA(){}
    public void funB }
    public void funC(){}
}

下面是一段模拟usb接口的代码:

//定义一个usb接口,供其他设备使用
public interface USB {
    public static final String VERSION= "USB 3.1";
    public abstract void start();
    void stop(); //接口中的方法默认是public abstract,可以略写
}

//定义u盘,实现usb接口的方法
class Flash implements USB{
    public void start(){
        System.out.println("U盘开始使用");
    }
    public void stop(){	//接口中的stop()方法没写权限,但要知道其默认是public,所以这里的权限也要是public
        System.out.println("U盘停止使用");
    }
}

//定义一个打印机,实现usb接口的方法
public class Printer implements USB{
    public void start(){
        System.out.println("打印机开始工作");
    }
    public void stop(){
        System.out.println("打印机停止工作");
    }
}

//定义计算机类
public class Computer {
    public void plugin(USB u){  //电脑有插入和拔出usb设备的方法
        u.start();
        u.stop();
    }
}

//一个测试类
public class TestUSB{
    public static void main(String[] args) {
        Computer c = new Computer();
        c.plugin(new Flash());
        c.plugin(new Printer());
    }
}

程序执行结果:

U盘开始使用
U盘停止使用
打印机开始工作
打印机停止工作

image

从以上的对象可以看出抽象类的优点比接口更多,但是单继承这一局限完全掩盖了抽象类的优点,所以实际中能用接口就用接口。

接口新特性

随着一些接口被广泛使用,其中的功能可能不够用了,那么就需要添加新的抽象方法。如果一个接口添加了新的抽象方法,那么所有实现此接口的子类都必须覆写此方法,如果一个接口有几十万个子类,那么覆写的任务非常繁重。所以Java引入了新的特性,可以在接口中定义普通方法或静态方法,子类可以根据需要来自行决定是否覆写。
如果要在接口中定义普通方法(默认方法),必须使用public default关键字。如果想要定义静态方法,使用public static关键字。

  • 接口的新成员
    • 默认方法(Java8):默认方法不是抽象方法,所以不强制被重写,但是可以被重写。重写的时候去掉default关键字。public可以省略,default不能省略

    • 静态方法(Java9):定义格式和普通类中的静态方法完全一样。但是接口中的静态方法只能通过接口名调用,不能通过实现类名或者对象名调用。public可以省略,static不能省略

    • 私有方法(java9):Java 9中新增了带方法体的私有方法,这其实在Java 8中就埋下了伏笔:Java 8允许在接口中定义带方法体的默认方法和静态方法。这样可能就会引发一个问题:当两个默认方法或者静态方法中包含一段相同的代码实现时,程序必然考虑将这段实现代码抽取成一个共性方法,而这个共性方法是不需要让别人使用的,因此用私有给隐藏起来,这就是Java 9增加私有方法的必然性。

      • 格式1

        private 返回值类型 方法名(参数列表) { }

        private void show() {  
        }
        
      • 格式2

        private static 返回值类型 方法名(参数列表) { }

        private static void method() {  
        }
        
interface IMessage{
    public abstract void print();	//抽象方法,必须覆写
    public default void fun(){	 //Java的新特性允许在接口中定义普通抽象方法,子类可以根据需要来覆写
        System.out.println("接口中的普通方法");
    }
    public static void show(){
        System.out.println("接口中的静态方法");
    }
}
class MessageImpl implements IMessage{
    public void print(){
        System.out.println("快上车");
    }
}

public class Demo{
    public static void main(String[] args) {
        MessageImpl m = new MessageImpl();
        m.print();
        m.fun();
    }
}

抽象类和接口的区别

  • 成员区别

    • 抽象类

      ​ 变量,常量;有构造方法;有抽象方法,也有非抽象方法

    • 接口

      ​ 常量;抽象方法(新特性也有非抽象方法)

  • 关系区别

    • 类与类

      ​ 继承,单继承

    • 类与接口

      ​ 实现,可以单实现,也可以多实现

    • 接口与接口

      ​ 继承,单继承,多继承

  • 设计理念区别

    • 抽象类

      ​ 对类抽象,包括属性、行为

    • 接口

      ​ 对行为抽象,主要是行为

posted @ 2021-08-27 17:57  黄了的韭菜  阅读(190)  评论(0编辑  收藏  举报