查看原文
其他

【图文+代码】不客气的说,这可能是你距离深入理解Java接口最近的一次

博文视点学院 博文视点Broadview 2021-07-07

全文2420字,预计阅读时间5分钟

文 | 选自《Java无难事——详解Java编程核心思想与技术》 

图 | 博文视点学院(部分素材来源网络,侵删)


有不少学习Java的同学一直有个疑问,不仅在初学者中很普遍,连许多经验丰富的老手也很难表述清楚,那就是:


Java接口到底是什么?


有多疑惑呢,在搜索引擎某应上搜索关键词“接口是什么”,相关结果900w+


当然不排除有对其他接口的疑问,但Java接口还是疑问中的主力军


看得出来,这个问题实在是太伤脑筋了。解答的文章也不少,不过越解释越复杂的也不在少数。



别急,今天这篇内容,图文干货含量拉满,认真阅读,可能是距离你深入理解Java接口最近的一次。



深入接口——通信双方的协议


接口有一个更重要的作用,就是作为模块与模块之间通信的协议。


在软件领域,一直以来都希望能够实现像硬件生产一样,不同的零部件由不同的厂商生产,然后按照标准的接口进行组装,得到成品。


不同的零部件由不同厂商生产,按照标准的接口进行组装


以计算机为例,要组装一台计算机,我们需要主板、CPU、显卡、内存等配件,虽然这些配件是由不同厂家生产的,但这并不影响我们组装成一台计算机,我们只需要将这些配件插在主板的对应插槽中就可以了,因为主板生产商和其他配件生产商都会针对某个插槽定义的规范进行生产,而配件在主板上的这些插槽就类似于Java中的接口


在大型软件系统中,通常都是多人协作开发,将整个系统进行拆解,划分出子系统和模块,然后分工协作,不同的开发人员负责不同的模块开发。

大型软件系统


而模块之间如何调用,则可以通过接口来约定,也就是说,接口可以作为模块与模块之间通信的协议。定义接口,相当于制定了模块之间通信的协议,两个模块要想通过接口进行通信,那么必然是一个模块实现了接口,提供了接口中声明的方法实现,而另一个模块则通过接口来调用其实现。


模块与模块之间通信的协议



有人可能被这个叙述绕晕了。别急,毕竟Talk is cheap,让我们来直接show the code, 尝试用代码示例组装一台Java牌计算机。 



计算机组装的代码示例


首先,我们定义两个接口CPU和GraphicsCard,代表主板上的CPU和显卡接口。如代码6.17和代码6.18所示。


代码6.17

package computer;

public interface CPU {
    void calculate();
}


代码6.18

package computer;

public interface GraphicsCard{
    void display();
}


前面说了,通过接口通信的双方,必然有一方要实现接口,另一方通过接口来调用其实现。上面两个接口定义了CPU和显卡需要实现的方法,于是CPU厂商和显卡厂商根据各自的接口定义开始生产相应的产品,如代码6.19和代码6.20所示。


代码6.19

package computer;

public class IntelCPU implements CPU {
    public void calculate() {
        System.out.println("Intel CPU calculate.");
    }
}


代码6.20

package computer;

public class NVIDIACard implements GraphicsCard {
    public void display() {
        System.out.println("Display something");
    }
}


IntelCPU类和NVIDIACard类分别给出了CPU接口和GraphicsCard接口的实现。


接下来该轮到主板登场了,主板上应该有CPU和显卡的插槽,从软件的角度来说,就是主板类应该持有CUP和显卡接口的引用,如代码6.21所示。


代码6.21

package computer;

public class Mainboard {
    private CPU cpu;
    private GraphicsCard gCard;

    public void setCpu(CPU cpu) {
        this.cpu = cpu;
    }

    public void setGraphicsCard(GraphicsCard gCard) {
        this.gCard = gCard;
    }

    public void run(){
        System.out.println("Starting computer...");
        cpu.calculate();
        gCard.display();
    }
}


在Mainboard类中,包含了两个私有的实例变量:cpu和gCard,它们的类型分别是CPU和GraphicsCard接口类型。


我们知道,接口是不能直接实例化对象的,真实的CPU和GraphicsCard对象是通过setCpu和setGraphicsCard方法传递进来的,至于真实的CPU和显卡对象是什么,我们需要知道吗?不需要,我们只需要知道传进来的对象已经实现了对应的接口就可以了。这就像我们买主板时,不需要关心主板上的相应插槽最终插的是哪个厂商的配件一样,因为我们知道所选购的配件都是符合插槽规范的,可以和主板一起工作。


配件(如内存条)可以来源于不同厂家,只要接口标准一致,就可以互通使用


在Mainboard类的run方法中,调用CPU接口和GraphicsCard接口的方法,完成计算机的启动与显示工作。


Mainborad类只是与CPU和GraphicsCard接口打交道,并没有依赖于具体的实现类,所以在组装计算机时,可以任意创建实现了CPU和GraphicsCard接口的类的对象,然后“安装”到主板上。


最后,我们要组装计算机了,也就是编写一个Computer类,如代码6.22所示。


代码6.22

package computer;

public class Computer {
    public static void main(String[] args) {
        Mainboard mb = new Mainboard();
        mb.setCpu(new IntelCPU());
        mb.setGraphicsCard(new NVIDIACard());
        mb.run();
    }
}


从这个例子中可以看到,Mainboard类并不关心“插”在它上面的CPU和显卡的具体类型,它只需要按照CPU和GraphicsCard接口中声明的方法使用显卡和CPU即可。而Computer类的main方法创建了CPU和GraphicsCard的实现对象,并通过setXxx方法把CPU和显卡“插”到主板上,接着调用Mainboard类的run方法启动计算机运行。


对于上面的例子来说,Mainboard类可以由一个人来开发,IntelCPU类可以由一个人来开发,NVIDIACard类可以由一个人来开发,而这三个人只需要按照CPU和GraphicsCard接口中声明的方法来进行编码就可以了,最终的程序通过Computer类来组装。




通过以上的学习,大家可以看出,深入理解Java接口其实并不难,只要找对方法,理解起来简直是so easy的地步。



但困难的是,Java学习中的要点、难点还要很多,如何都能把这些深奥的知识以最浅显的语言讲述出来。


好在这样困难的问题,已经可以通过这样一本书来完美解决上文中循序渐进,幽默风趣的叙述方式,贯穿了整本书,可以一步步引导你去掌握Java开发方法。




相关图书


《Java无难事——详解Java编程核心思想与技术》

孙鑫 著


本书系统地讲解Java开发人员需要掌握的核心知识,按照中国人的思维习惯,由浅入深、循序渐进、引导式地带领你快速掌握Java知识。


本书讲解了依赖注入(IoC/DI)容器、面向切面编程(AOP)、对象关系映射(ORM)框架的实现原理,同时还给出了并发编程领域中经常用到的线程池的实现。涵盖了从Java 5到Java 11的所有重要新特性,不仅适合初学Java编程的读者,也适合有一定经验的读者,甚至对于正在从事Java开发工作的读者也适用。
本书同时在每个关键知识点旁都配备了相应的视频二维码,可以随看随学。

还有来自作者孙鑫老师的倾情讲解:


▼扫码获取本书详情▼



最后的最后,是这本书也是博文菌带给大家的祝愿,希望大家:


Java再无难事





如果喜欢本文
欢迎 在看留言分享至朋友圈 三连


 热文推荐  






点击阅读原文,了解本书详情~

    您可能也对以下帖子感兴趣

    文章有问题?点此查看未经处理的缓存