导读:前两天闲着没事儿,看了本书,然后写了点代码,在接口里面写了默认方法实现,因为书上说这个特性是从java8开始的,我还特地给测了一下java7. 没过几天,就有一个技术分享会,刚好也是讲java8特性,然后,顿时就觉得世界观被毁了!怎么回事呢,看下文吧:
还记得,当年我刚面试的时候,面试官问我接口和抽象类什么区别,我张口就来了传说中的标准答案,那时候是解释不清楚接口和抽象类各自的用途的和来源的,就记得我说了很重要的一条就是:抽象类里面可以有方法实现,而接口是不可以的。哈哈哈哈,java8出来之后,我竟无言以对!
一、基本概念
1.1,抽象类
从语义的角度来看,抽象类是从多个具体类中抽象出来的父类,它具有更高层次的抽象,体现了is-a的逻辑。从多个具有相同特征的类中抽象出一个抽象类,以这个抽象类作为其子类的模板,从而避免了子类设计的随意性。
从根本上来说,抽象类体现的是一种模板模式的设计,它作为子类的通用模板,允许其子类在它的基础上扩展、改造,但是,子类总体上会大致保留抽象类的行为方式!(就跟个如来佛似的,孙悟空那么厉害,我允许你蹦跶蹦跶蹦,但你这猴子,还得听我的是不)
1.2,接口
抽象类是从多个类中抽象出来的模板,将抽象更进一步,就可以折腾出一个更高逼格的别样“抽象类”——接口!体现了has-a的逻辑。
接口定义了某一批类所需要遵守的规范,它并不关心这些类的内部状态数据,也不关心这些类里方法的实现细节,它只规定这批类里必须提供某些方法,满足实际需要。它体现的是一种规范和实现向分离的设计哲学。
八卦模式:接口让我想起了邓爷爷的一句话:管他黑猫白猫,抓到耗子就是好猫!接口就是这样子的一个体现:管你动物类植物类,接口实现了就是好的! 要是当年如来佛公布一个去西天的接口,然后定义了一个取经的方法,会发生什么? (群魔乱舞,各显神通,但是这妖魔神仙多了,嘿嘿。。。。) 拿要是他老人家公布的是一个去西天的抽象类,然后定义了一个取经的方法,又会发生什么?
二、思考过程
2.1,体现在内存分配
因为接口里面只能是类成员变量、类方法或默认方法、内部类等,而抽象类里面的变量和方法可以是实例成员变量或方法。我就在想,如果使用接口的话,那么方法和变量势必会在JVM启动时,就会被加载分配到内存,从而增加程序启动的开销,反之抽象类就不一样了。 不过,我这个想法被否了,说是现在的虚拟机经过一带一带的改进,从这个角度上来说,使用接口和抽象类的内存影响差不多!除非我刻意写了坏味道的代码。。。本宝宝表示不懂啊
2.2,体现在多继承
因为一个类可以同时实现很多个接口,而一个类不可以同时继承多个类
2.3,体现在访问控制层面
又回到了接口可用的访问控制,方法只能是静态或默认,变量只能是静态 final等,而接口默认的访问控制是public。反之抽象类,可以是public、private、protected等!
知道我为什么这么纠结这个抽象类和接口的区别吗?因为从java8出来之后,有人问你觉得抽象类还有存在的必要吗,抽象类可以实现的,接口都可以做到!然后,那时我还是个宝宝,但后来越想越不对,所谓存在即合理对吧!
三、主要异同点
3.1,相同点
1,都不能被实例化,位于继承树的顶端,用于被其他类实现和继承
2,都可以包含抽象方法,实现接口或继承抽象类的普通子类都必须实现这些抽象方法
3.2,不同点
1,目的和作用不同
接口是系统与外界交互的窗口(模块或系统之间提供服务窗口,有听说是调用抽象类的不?)它体现的是一种规范。对于接口的实现者,它规定了实现者必须提供的服务;对于接口的调用者,它则规定了调用者可以调用的服务,以及如何调用这些服务。当在一个程序中使用接口时,接口时多个模块间的耦合标准;当在多个程序中时,它就是多个程序之间的通信标准。
抽象类是系统中多个子类的共同父类,它可以被当成系统实现过程中的中间产品,这个产品已经实现了系统的部分功能,但它并不是一个成熟的产品,必须由其子类去进一步完善!
PS:有没有感觉接口的设计层面和抽象类不一样?想一想机房收费系统,接口可以作为独立的一层去设计,而没有抽象类层!
2,在用法上不同
抽象类可以包含普通方法;接口不能定义静态方法(注意区别java8接口可以有静态和默认方法实现);抽象类可以定义普通成员变量;抽象类可以拥有构造器,让其子类利用它完成抽象类的初始化操作;接口无法拥有初始化块;接口可以弥补java单继承的不足。
四、总结
我总觉得抽象类和接口比起来,接口更好用,先不说抽象类继承破坏了父类的封装性(用组合模式解决)再着就是目前的使用过程中得到的体会,比如说Animal A=new Dog();这个向上转型,还有就是如果程序真的出了点问题需要改的话,那么势必也会改到这一行代码,现在Spring容器通过IOC创建对象,这个可能就不算事儿了!