• Java-接口


    认识接口

    接口的概念

    现实中电脑 相机 笔记本等都有USB接口,且任何一个U盘都可以插入。这是因为所有的厂家都遵循了USB接口的标准和规范。才可以让全部的USB接口和产品兼容匹配。

    JAVA接口是一系列方法的声明,是一些方法特征的集合。一个接口只有方法的特征没有方法的实现,因此这些方法可以在不同的地方被不同的类实现,因此这些实现可以具有不同的行为。

    接口可以理解为一种特殊的类,在这个特殊的类中,里面只有 全局常量和公共抽象方法(jdk8以后可以有默认方法和静态方法)。 接口是解决Java无法多继承的一种手段,实际运用中接口更多是指定标准的作用。

    抽象类和接口的区别

    抽象类中可以有正常类的所有成员:代码块 静态代码块 构造器 属性…
    接口中只能有全局常量和抽象方法和静态方法和默认方法。静态方法与默认方法必须有方法体
    ps: ( 抽象类可以存在非抽象方法,接口只能存在抽象方法)java8以后接口中可以有静态方法和default修饰符的默认方法(有方法体)

    接口的特点

    就像一个普通类一样接口也有方法和属性,但是在接口中声明的方法默认是抽象的。只有方法标识符,没有方法体
    普通方法默认以 public abstract修饰符修饰,也可以不写但是默认这两个修饰符还是存在的。

    1. 接口规范了一个类必须要做的事情。一旦某个类要实现这个接口,就得实现接口中所有的抽象方法
    2. 如果一个类实现了接口中所有的方法,但是却没有方法体,那么这类一定是抽象类

    接口的语法

    声明一个类 我们是用 class 类名 。同理接口是用 interface 接口名声明一个接口

    interface 接口名{
    //全局变量属性
    // 抽象方法
    // 静态方法
    // default修饰的默认方法
    }
    class 类名 implements 接口名{
    //该类自己的属性和方法
    //实现接口的抽象方法
    }

    public interface UsbInterface {
     //全局变量public static final可以不写,结果是一样的。默认就是这三个修饰符
     public static final int num =1 ;
     //抽象方法 public abstract可以不写,结果是一样的
     public abstract void read();
     //默认方法 必须有方法体
     default void work(){}
     //静态方法 必须有方法体
     static void wee(){}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    在接口中所有的方法都必须只声明方法标识,而不实现方法体。因为具体的实现是由基础该接口的类去实现的。

    1. 接口中的方法默认是 public abstract修饰的 ,也就是抽象方法
    2. 接口中的属性默认是public static final 修饰的,也被称为全局变量
    3. 一个类想要实现一个接口,需在类名后面使用imlpements 关键字 带 接口名,类似于继承

    入门演示:

    public interface UsbIntelface {//接口
        public static final int num = 90;
        public abstract void inMethod();
    }
    class TestInterface implements UsbIntelface{//实现接口
        @Override
        public void inMethod() {//重写接口的抽象方法
            System.out.println("实现了接口的inMethod方法"+num);
        }
        public static void main(String[] args) {
            new TestInterface().inMethod();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    入门案例
    在现实生活中如果某个设备想向电脑读取或者写入一些东西,最常见的方法就是通过USB接口。只要带有USB功能的设备就可以通过USB接口与电脑完成交互。在这可以认为USB就是一种功能,一种标准,一种接口。只要实现了USB标准的设备就是有了USB功能。我们可以通过代码模拟一下。
    比如触手可及的键盘和鼠标,默认USB接口中有读取和写入的功能。

    public interface UsbIntelface {
        public abstract void read();
        //也可以直接写 void read,结果是一样的
        void write();
    }
    class keyboard implements UsbIntelface{
        @Override
        public void read() {
            System.out.println("键盘正在读取...");
        }
        @Override
        public void write() {
            System.out.println("键盘正在写入...");
        }
    }
    class mouse implements UsbIntelface{
        @Override
        public void read() {
            System.out.println("鼠标正在读取...");
        }
        @Override
        public void write() {
            System.out.println("鼠标正在写入...");
        }
    }
    class Test122{
        public static void main(String[] args) {
            keyboard k = new keyboard();
            k.read();
            k.write();
            mouse m = new mouse();
            m.read();
            m.write();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35

    运行结果:
    键盘正在读取…
    键盘正在写入…
    鼠标正在读取…
    鼠标正在写入…

    • 接口标准演示
      假如现在有2个程序员,分别要链接mysql和Oracle。分别要有连接和断开的方法
      如果不定义标准就会出现 第一个程序员连接数据库的方法名是 F 断开方法是F2 第二个程序员连接方法是connect 断开方法名是close。这样的话会导致,无法统一,调用的复杂度变高。

    而使用接口定义标准就可以很好的规范程序员,或者指定一个标准。
    例如:定义一个接口 里面有抽象方法connect是连接到数据库,close方法是断开数据库。
    然后让两个程序员分别在两个类去实现这个接口完成要求的功能。再根据java的多态使用接口,就可以规范代码,和降低复杂度。
    代码演示:

    public interface AInterface {
        void connect();
        void close();
    }
    class Mysqlinterface implements AInterface{
        @Override
        public void connect() {
            System.out.println("连接到Mysql");
        }
        @Override
        public void close() {
            System.out.println("断开Mysql");
        }
    }
    class Oraclelinterface implements AInterface{
        @Override
        public void connect() {
            System.out.println("连接到Oracle");
        }
        @Override
        public void close() {
            System.out.println("断开Oracle");
        }
    }
    class testinterface{
        public static void str(AInterface aInterface){
            aInterface.connect();
            aInterface.close();
        }
        public static void main(String[] args) {
            Mysqlinterface m = new Mysqlinterface();
            Oraclelinterface o = new Oraclelinterface();
            testinterface.str(m);
            testinterface.str(o);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36

    接口的使用细节

    1. 接口不能被实例化,接口中大都是抽象方法,没有具体的实现。更没有具体的实例
    2. 接口中的所有方法都是public修饰的方法,抽象方法 public abstract可以省略不写,跟写了没区别
    3. 一个普通类实现接口,必须将接口的所有抽象方法都实现掉
    4. 抽象类实现接口,可以不用实现接口中的抽象方法
    5. 一个类只能继承一个父类,但是可以同时实现多个接口。使用,号隔开
    6. 接口中的属性只能是final的,且是public static final修饰符。可以通过接口名.属性名在别的地方调用修改验证
    7. 接口中属性的访问形式:接口名.属性名
    8. 接口不能继承类,但是同时继承多个别的接口使用,号隔开
    9. 接口的修饰符 只能是public和默认不写,和类的修饰符是一样的

    小结练习

    下列语法是否正确?如果正确会输出什么

    interface A{
    int a = 23;
    }
    class B implements A{//正确,因为接口中没有抽象方法,所以不用实现
    }
    //主类main方法中
    B b = new B();
    System.out.println(b.a);//23
    System.out.println(A.a);//23
    System.out.println(B.a);//23可以把implement看成一种另类的继承extends
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    接口和继承

    举例说明:
    猴子会爬树,这是与之俱来的功能。或者是猴子他爸教给他的能力。这种就是继承 LittleMmonkey extends Oldmonkey。
    但是这只小猴子比较好学,他想像鱼一样游泳。或者像鸟一样飞翔。但是它本身又没有这个功能,它的父类也没有这个能力,所以它得通过自己去学习,实现游泳和飞翔的能力。

    代码演示:

    public class OldMonkey {
        String name;
        public void tree(){
            System.out.println("猴子上树");
        }
    }
    interface Fish{
        void swimming();
    }
    interface Bird{
        void fly();
    }
    class LitteMonkey extends OldMonkey implements Fish,Bird{
        @Override
        public void swimming() {
            System.out.println(name+"通过学习,学会了游泳");
        }
        @Override
        public void fly() {
            System.out.println(name+"通过学习,学会了飞");
        }
    }
    class testm{
        public static void main(String[] args) {
            LitteMonkey li = new LitteMonkey();
            li.tree();
            li.swimming();
            li.tree();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

    综上:由于java中不允许多继承,所以接口可作为继承的一种补充拓展,或多继承的替代。

    • 接口和继承解决的问题不同

    继承的价值在于:解决代码的复用性和可维护性
    接口的价值在于:设计好各种规范,使其他类更加灵活

    • 接口比继承更加灵活

    继承需要满足 is a 的关系。例如猫是一个动物。而接口只需要满足like a 的关系,猴子像一只鸟,也是可以的,因为并没有改变它的物种。

    • 接口在一定程度上实现代码解耦

    接口的多态

    接口的多态在运用上和继承体现的多态大差不差,概念大致相同。

    1.接口参数的多态
    和继承一样,在定义一个方法时,形参使用的是父类,实际传入子类是允许的。接口也是同理,在定义方法时使用接口类型,实际运行时传入实现了接口的类,也是允许的。
    案例:

    public class OldMonkey implements USBinterface{
        @Override
        public void fly() {
            System.out.println("正在飞");
        }
    }
    interface USBinterface{
        void fly();
    }
    class testm{
        public void deFly(USBinterface usBinterface){//形参是接口类型
            usBinterface.fly();
        }
        public static void main(String[] args) {
            OldMonkey om = new OldMonkey();
            new testm().deFly(om);//实际传入运行的是实现接口的类
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    2.接口的多态数组
    接口的多态数组和继承体现的差不多,只不过继承是父类的数组存放着子类对象。而接口是接口类型的数组 存放着实现了接口的类对象

    案例体现:
    1.Usb数组种存放Phone和相机对象
    2.Phone类有一个特别的方法call()
    3.相机有一个特别的方法photo()。
    4.Usb是一个接口类型,有抽象方法work()
    5.遍历这个数组,且除了调用work方法外都调用一下各自的方法

    public class Homework {
        public static void main(String[] args) {
        Usb[] usbs = new Usb[2];
        usbs[0] = new Phone();
        usbs[1] = new Camera();
            for (int i = 0; i < usbs.length; i++) {
                usbs[i].work();
                //因为要分别调用各个类自己的方法,所以要先进行类判断,然后向下转型再调用自己的方法
                if (usbs[i] instanceof Phone){
                    ((Phone) usbs[i]).call();
                }
                if (usbs[i] instanceof Camera){
                    ((Camera) usbs[i]).photo();
                }
            }
        }
    }
    interface Usb{
        void work();
    }
    class Phone implements Usb{
        public void call(){
            System.out.println("正在打电话");
        }
        @Override
        public void work() {
            System.out.println("IPhone正在工作");
        }
    }
    class Camera implements Usb{
        public void photo(){
            System.out.println("正在拍照");
        }
        @Override
        public void work() {
            System.out.println("相机正在工作");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38

    3.接口的多态传递
    在继承种向上转型可以使用 父类的引用指向子类的对象,也可以使用爷爷类的引用指向子类的对象。
    在接口种也可以使用接口类型的引用指向实现了接口的类对象,那么接口B继承与接口A,是否可以用接口A的引用指向实现了接口B的类对象呢

    答案是可以的,因为B接口继承于A接口,而类想要implement接口B就必须把接口A和B的所有抽象方法都给实现了。因此他们也是有关系的。这就是接口的多态传递
    代码演示

    public class abc {
        public static void main(String[] args) {
            B b = new SON();
            A a = new SON();//多态传递
        }
    }
    interface A{
        void me();
    }
    interface B extends A{}
    class SON implements B{
        //必须实现A的抽象方法
        @Override
        public void me() {
            
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    接口练习

    1.下面代码是否有错误,怎么修改。

    interface A{int x = 0;}
    class B{int x = 1;}
    class C extends B implements A{
    public void px(){
    Sysem.out.println(x)}//错误点,编译器会不知道x是指谁,两个x是同级存在
    public static void main(String [] args){
    new C().px();
    }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    如果要输出父类的x就使用super.x,如果要输出接口的x就使用 A.x.


  • 相关阅读:
    如何实现基于 RADIUS 协议的双因子认证 MFA?
    单例模式详解【2023年最新】
    华为22级专家十年心血终成云原生服务网格进阶实战文档,是真的6
    Oracle数据不常用的函数
    Python字符串介绍详解
    modbus的协议
    欧洲历史脉络
    UOS 开启 VisualStudio 远程调试 .NET 应用之旅
    【DevOps】Gitlab的安装与升级
    联通面试题
  • 原文地址:https://blog.csdn.net/WINorYU/article/details/127886085