【Java基础】接口和抽象类之间的对比
Java 中的接口和抽象类之间的对比
一、接口
Interface,将其翻译成插座可能就更好理解了。我们通常利用接口来定义实现类的行为,当你将插座上连接笔记本的三角插头拔掉,换成微波炉插上去的时候,你就会发现,这两样东西它都是三角插头的。那么这个三角插头就可以视为一种规则,而这两样电器就是两个实现了同样规则的构件了。因为实现了同样的规则,使得动态地将一个构件换成另外一个构件变得容易得多。那么在代码中也是相同地道理,当两个类实现了相同的接口,将客户端中原有实现类换成另外一个,就变得简单不过了。
首先,定义一个接口的代码如下:
[public] interface InterfaceName {
void fun1();
}
接口中可以拥有变量和方法,但是接口中定义的变量会被隐式默认为 public static final 变量,并且也只能是这样,如果你使用其他的修饰符修饰,编译时会报错。同样的,方法也会默认被 public abstract 修饰。但是,你只能定义一个方法,而不能有方法的实现类,接口中的方法只能是抽象方法,这一点就和抽象类不同了(抽象类可以有方法实现)。
而接口对应实现类的实例代码如下
public class ClassName implements InterfaceName, OtherInterface, [...] {
public void fun1() {
// do something ...
}
}
在 Java 中,类是单继承的,但是却可以继承多个接口,而接口可以继承多个接口。
二、抽象类
在 Java 语言中,类有两种:一种是具体类,另一种是抽象类。具体类可以实例化,抽象类不可以实例化。所以在这里可以想到,抽象类创建出来,就是用来被继承的,毕竟你不能用一个无法实例化的类来为你完成什么功能(当然这里不包括静态变量和方法的调用,但是如果只是用来做这些,那你为什么要把这个类声明为抽象类呢?)
在了解抽象类之前,我们先了解抽象方法:抽象方法是一种特殊的方法,它只有声明,而没有具体的实现:
abstract void fun1();
在抽类中的定义的抽象方法必须使用 absract 关键字修饰,同样抽象类也需要被 abstract 关键字修饰
[public] abstract class AbstractClassName {
abstract void fun1();
}
如果一个类继承了抽象类,那么子类就必须要实现抽象类中定义的所有抽象方法,除非将子类也定义为抽象类。
三、对比
语法功能上的对比
- 接口只能包含抽象方法,而抽象类即可有普通方法,也能有抽象方法
- 接口不包含构造方法,抽象类中可以包含构造方法以备继承类扩充
- 接口中不能含有静态代码块以及静态方法,而抽象类可以有静态代码块和静态方法
- 接口只能定义静态常量属性,抽象类既可以定义普通属性,也可以定义静态常量属性
设计思想上的对比
我们口头上常说:实现一个接口,继承一个抽象类。其实这句话就已经将接口和抽象类之间的区别表现出来了。
接口更多的是被视为一种契约,契约里的方法是让你来实现的。当别人给定你一个接口,你就按接口中定义的方法去实现,那么就是在实现一份契约了。所以接口是其实是一些方法特征的集合,这些方法特征当然来自于具体方法,但是它们一般都是来自于一些在系统中不断出现的方法。一个接口只有方法的特征,而没有方法的实现,因此这些方法在不同的地方被实现的时候,可以具有不同的行为。
而抽象类更多的是被视为一个模板,它提供的是一个继承的出发点,是子类中的共有部分的集中实现。所以抽象类是一种模板式的设计,什么是模板式设计?最简单例子,大家都用过 ppt 里面的模板,如果用模板A设计了 ppt B和 ppt C,ppt B 和 ppt C 公共的部分就是模板A了,如果它们的公共部分需要改动,则只需要改动模板A就可以了,不需要重新对 ppt B 和 ppt C 进行改动。也就是说对于抽象类,如果需要添加新的方法,可以直接在抽象类中添加具体的实现,子类可以不进行变更;而对于接口则不行,如果接口进行了变更,则所有实现这个接口的类都必须进行相应的改动。
四、继承复用与规范实现之间的选择
接口是一种特殊的抽象类,那么在开发中,何时选用接口?何时选用抽象类呢?
- 优先选用接口
满足以下全部条件时,选用抽象类
子类是父类的一个特殊类,而不是父类的一个角色,也就是要区分 “Has-A” 与 “Is-A” 两种关系的不同。Has-A 关系应当使用聚合关系描述,而只有 Is-A 关系才符合继承关系。
不会出现需要将子类换成另外一个类的子类的情况
子类具有扩展父类的责任。而不是具有置换掉(Override)或注销掉(Nullify)父类的责任。如果子类需要大量地置换掉父类的行为,那么这个子类就不应当成为这个父类的子类。
只有父类和子类属于同一种分类的时候,才可以使用继承,不要从工具类继承。
五、Java 8 的新特性
从 Java 8 开始,接口也可以拥有默认的方法实现,这是因为不支持默认方法的接口的维护成本太高了。在 Java 8 之前,如果一个接口想要添加新的方法,那么要修改所有实现了该接口的类。
public interface InterfaceExample {
void func1();
default void func2(){
System.out.println("func2");
}
}
public class InterfaceImplementExample implements InterfaceExample {
@Override
public void func1() {
System.out.println("func1");
}
}
public static void main(String[] args) {
InterfaceExample example = new InterfaceImplementExample();
example.fun1();
example.fun2();
}
六、参考
- 《Java与模式》
- https://www.cnblogs.com/felixzh/p/5938544.html
- https://www.cnblogs.com/devinzhang/archive/2011/12/24/2300260.html
- https://github.com/CyC2018/CS-Notes/blob/master/notes/Java 基础.md#抽象类与接口
【Java基础】接口和抽象类之间的对比的更多相关文章
- Java基础接口和抽象类区别(二)
抽象类 在了解抽象类之前,先来了解一下抽象方法.抽象方法是一种特殊的方法:它只有声明,而没有具体的实现.抽象方法的声明格式为: 抽象方法必须用abstract关键字进行修饰.如果一个类含有抽象方法,则 ...
- 浅谈java中接口与抽象类之间的异同
刚学习java的时候,总觉得接口和抽象类很像,但又说不上具体有什么区别.今天静下来,翻翻书,查查资料,做个小结.首先举两个例子,看看interface和abstract class 在“外形”上有啥异 ...
- java基础——接口与抽象类的区别
(1)首先接口和抽象类的设计目的就是不一样的.接口是对动作的抽象,而抽象类是对根源的抽象. (2)对于抽象类,一个类只能继承一个抽象类.但是一个类可以同时实现多个接口. (3)接口是公开的,里面不能有 ...
- Java基础——接口和抽象类
接口(interface) 什么是接口? 接口时抽象方法的合集.接口不可以被直接被实例化. 为什么要使用接口? 为了扩展.Java不支持多继承,但是通过接口就可以实现“多继承” 制定规则.接口就是规则 ...
- Java基础--接口和抽象类的区别
任何不谈使用方法的空理论都是耍流氓 使用场景 · 如果你拥有一些方法并且想让它们中的一些有默认实现,那么使用抽象类吧(Java1.8中接口也可以这么做了) · 如果你想实现多重继承,那么你必须使用接口 ...
- 慢慢人生路,学点Jakarta基础-深入剖析Java的接口和抽象类
在java面向对象编程的,抽象类和接口始终存在有疑问的地方,因为两者太多相似有太多不同,在刚开始学习的时候经常弄的不对,使用情景搞混,今天来总结之前学习Java中接口和抽象类的问题. 抽象类 了解:只 ...
- Java中接口和抽象类的比較
Java中接口和抽象类的比較-2013年5月写的读书笔记摘要 1. 概述 接口(Interface)和抽象类(abstract class)是 Java 语言中支持抽象类的两种机制,是Java程序设计 ...
- Java:接口和抽象类,傻傻分不清楚?
01. 来看网络上对接口的一番解释: 接口(英文:Interface),在 Java 编程语言中是一个抽象类型,是抽象方法的集合.一个类通过继承接口的方式,从而来继承接口的抽象方法. 兄弟们,你们怎么 ...
- 深入理解Java的接口和抽象类(转)
深入理解Java的接口和抽象类 对于面向对象编程来说,抽象是它的一大特征之一.在Java中,可以通过两种形式来体现OOP的抽象:接口和抽象类.这两者有太多相似的地方,又有太多不同的地方.很多人在初学的 ...
随机推荐
- Swoole高效跟传统的web开发有什么区别?
一.swoole的运行模式 Swoole高效跟传统的web开发有什么区别,除了传统的LAMP/LNMP同步开发模式,swoole的异步开发模式是怎么样的. 1.1.传统web开发模式 PHP web开 ...
- iPhone唯一标识符
为了区分iPhone设备,就要用到iPhone的唯一标识符唯一标识符包括:UDID(唯一设备标识符).identifierForVendor(供应商标识符).advertisingIdentifier ...
- 使用WebClient实现断点续传 重写
早上下个东西,半天不动,火冒三丈,我可是100M光纤... WebClient.Httpclient.HttpWebRequest.WebRequest 我选了了WebClient因为他封装的够好 断 ...
- 551. 学生出勤纪录 I
给定一个字符串来代表一个学生的出勤纪录,这个纪录仅包含以下三个字符: 'A' : Absent,缺勤 'L' : Late,迟到 'P' : Present,到场 如果一个学生的出勤纪录中不超过一个' ...
- KafkaManager2.0.0.2安装与使用
KafkaManager 是雅虎开源的一款 针对kafka集群的web管理工具, 具体功能和介绍就不再这细讲 kafka-manager github官网 https://github.com/ya ...
- 大数据学习笔记——Spark工作机制以及API详解
Spark工作机制以及API详解 本篇文章将会承接上篇关于如何部署Spark分布式集群的博客,会先对RDD编程中常见的API进行一个整理,接着再结合源代码以及注释详细地解读spark的作业提交流程,调 ...
- ELK-logstash基本用法
一:logstash介绍 Logstash在elk系统中为数据存储,报表查询和日志解析创建了一个功能强大的管道链.Logstash提供了多种多样的 input,filters,codecs和outpu ...
- LRU算法与增强
概要本文的想法来自于本人学习MySQL时的一个知识点:MySQL Innodb引擎中对缓冲区的处理.虽然没有仔细研究其源码实现,但其设计仍然启发了我. 本文针对LRU存在的问题,思考一种增强算法来避免 ...
- Java获取配置文件中的属性
获取配置文件的属性值 example 目标配置文件jdbc.properties,现想要在java类里面调用opcl的url jdbc.url=jdbc:mysql://localhost:3306/ ...
- chrome显示正常,IE报400的错
发现是因为参数里面有一个是中文,应该是IE没有转码,所以会报错,只要用encodeURI()实现转码即可