抽象类和接口,你了解多少?

  现在的java开发一般都说面向接口编程,在开发过程中使用的最多的是给service层每个方法写一个接口,如果用到了DAO层,那么也是一个Mapper接口,之后的事情就交给mybatis框架去做了。总之编程过程中充斥着接口,有一个和接口很相似的叫做“抽象类”的不知道是否还记得。今天想聊聊接口和抽象类的那些事。

一、什么是接口,什么是抽象类

  接口和抽象类就像是一队孪生兄弟,有时候除了从定义上来区分,其他地方用什么似乎都是可以的。

  接口,可以理解为定义一组协议,一类操作流程。经常听到“你把这个类抽象出一个接口出来”这样的话,那么接口是什么样子,如在java的API中有AutoCloseable接口,

抽象类和接口,你了解多少?

该接口仅仅定义了一个close()方法,抛出Exception异常,看下该接口上的注释

抽象类和接口,你了解多少?

意思大概是close()方法不像java.io.Closeable接口中的close()方法需要幂等性,该接口不需要幂等性,同时强烈建议实现类或接口实现自己的close()方法。既然提到了java.io.Closeable那么我们看下该接口是什么样子的,抽象类和接口,你了解多少?

该接口继承了java.lang.AutoCloseale接口,且有自己的close()方法,该方法抛出的是IOException,也就是说该接口和IO相关。

从上面我们可以得出一个结论接口是可以继承接口的

我们比较java.lang.AutoCloseable和java.io.Closeable这两个接口,都是只有两个close()方法,但看java.lang.AutoCloseable接口,你根本看不出什么东西,它可以说是一个高度的抽象,仅仅是关闭一个资源,而且抛出的是Exception异常,简直太抽象了,感兴趣的可以阅读下该类上的注释。那么到了java.io.Closeable同样是一个close()方法,不过这里确实抛出一个IOExcetion异常,那么就是和IO相关的拉。从上面可以看出接口肯定是高度抽象的。反观我们平时写的代码,动不动就是一个接口,抽象程度肯定不够,

下面看下java.io.Closeable的一个实现类java.io.InputStream,你没看错就是平时使用的文件操作类InputStream,它不是一个接口,而是一个抽象类

抽象类和接口,你了解多少?

从上图可以看到InputStream实现了Closeable接口,且该抽象类中还有其他一些read()、skip()、avaliable()方法等。

先看下实现的close()方法吧,

抽象类和接口,你了解多少?

该方法是一个空方法,没用任何实现,意味着等待InputStream的子类去覆盖,例如BufferedInputStream是这样实现的,

抽象类和接口,你了解多少?

再回过头来看下InputStream类中的read()方法,

抽象类和接口,你了解多少?

这个方法是抽象的,而另外一个read()方法是有实现的,

抽象类和接口,你了解多少?

从这里可以看出,抽象类中可以有非抽象方法

 

  举了这么多的例子,无非是想大家对接口和抽象类能有一个感官上的认识,现在对其做个总结,

  接口定义了一组协议或标识某个功能,接口可以实现接口,接口中的方法都是public static final的。

  抽象类是一种特殊的类,无法实例化,只能被继承,只要类中有一个方法是抽象的那么该类就说抽象的,抽象类中可以有非抽象方法。

  java8开始接口中可以有default修饰的方法。

二、怎么使用接口,怎么使用抽象类

前面说了很多关于接口和抽象类的内容,那么接口和抽象类要怎么使用,想必定义都是不陌生的,类似,

package com.my.day01;  /**  * 汽车接口  * @date 2022/5/22 21:00  */ public interface CarInterface {     void run()throws Exception; }

抽象类,

package com.my.day01;  /**  * 抽象的汽车类  * @date 2022/5/22 21:02  */ public abstract class AbstractCar implements CarInterface {     @Override public void run() throws Exception {         System.out.println("running.....");     }     /**      * 加油      * 不同的car加的油不一样,有汽油、柴油,有92 95等      */     public abstract void fillGas();     /**      * 挂挡      */     public void gear() {         System.out.println("挂挡");     } }

上面就是接口和抽象类的使用,有个很重要的问题,什么时候该用接口什么使用该用抽象类,我有这样的一些想法,供参考。接口必须是高度抽象的,从所有的类中抽象出来公有的方法,那么这个方法就应该是在接口中;对于一些不是所有的类都有的行为,我们可以抽取到抽象类中实现为抽象方法,供不同的子类去实现。我认为接口和抽象类之间还是有不少区别的。

三、接口、抽象类的区别是什么

  接口和抽象类中有什么样的区别?难到不可以仅用其中一个吗?这个肯定是不行的。首先,接口定义的是一组规范,一组协议,她不负责任何实现,而在抽象类中是可以有非抽象方法的,也就是说抽象类可以提供一部分实现,仅把部分作为抽象供子类去覆盖;其次,现在都讲面向接口编程,你给人提供API的时候给一个抽象类那岂不是把你的实现也告诉别人了吗。

四、总结

  本文主要是由接口和抽象类这个基础点,带来的一些思考,越是常见的知识越容易被忽略。又不正之处欢迎指正。

 

发表评论

相关文章

当前内容话题