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基础】接口和抽象类之间的对比的更多相关文章

  1. Java基础接口和抽象类区别(二)

    抽象类 在了解抽象类之前,先来了解一下抽象方法.抽象方法是一种特殊的方法:它只有声明,而没有具体的实现.抽象方法的声明格式为: 抽象方法必须用abstract关键字进行修饰.如果一个类含有抽象方法,则 ...

  2. 浅谈java中接口与抽象类之间的异同

    刚学习java的时候,总觉得接口和抽象类很像,但又说不上具体有什么区别.今天静下来,翻翻书,查查资料,做个小结.首先举两个例子,看看interface和abstract class 在“外形”上有啥异 ...

  3. java基础——接口与抽象类的区别

    (1)首先接口和抽象类的设计目的就是不一样的.接口是对动作的抽象,而抽象类是对根源的抽象. (2)对于抽象类,一个类只能继承一个抽象类.但是一个类可以同时实现多个接口. (3)接口是公开的,里面不能有 ...

  4. Java基础——接口和抽象类

    接口(interface) 什么是接口? 接口时抽象方法的合集.接口不可以被直接被实例化. 为什么要使用接口? 为了扩展.Java不支持多继承,但是通过接口就可以实现“多继承” 制定规则.接口就是规则 ...

  5. Java基础--接口和抽象类的区别

    任何不谈使用方法的空理论都是耍流氓 使用场景 · 如果你拥有一些方法并且想让它们中的一些有默认实现,那么使用抽象类吧(Java1.8中接口也可以这么做了) · 如果你想实现多重继承,那么你必须使用接口 ...

  6. 慢慢人生路,学点Jakarta基础-深入剖析Java的接口和抽象类

    在java面向对象编程的,抽象类和接口始终存在有疑问的地方,因为两者太多相似有太多不同,在刚开始学习的时候经常弄的不对,使用情景搞混,今天来总结之前学习Java中接口和抽象类的问题. 抽象类 了解:只 ...

  7. Java中接口和抽象类的比較

    Java中接口和抽象类的比較-2013年5月写的读书笔记摘要 1. 概述 接口(Interface)和抽象类(abstract class)是 Java 语言中支持抽象类的两种机制,是Java程序设计 ...

  8. Java:接口和抽象类,傻傻分不清楚?

    01. 来看网络上对接口的一番解释: 接口(英文:Interface),在 Java 编程语言中是一个抽象类型,是抽象方法的集合.一个类通过继承接口的方式,从而来继承接口的抽象方法. 兄弟们,你们怎么 ...

  9. 深入理解Java的接口和抽象类(转)

    深入理解Java的接口和抽象类 对于面向对象编程来说,抽象是它的一大特征之一.在Java中,可以通过两种形式来体现OOP的抽象:接口和抽象类.这两者有太多相似的地方,又有太多不同的地方.很多人在初学的 ...

随机推荐

  1. luogu P2985 [USACO10FEB]吃巧克力Chocolate Eating

    题目描述 Bessie拿到了N (1 <= N <= 50,000)块巧克力.她决定想个办法吃掉这些巧克力,使得它在吃巧克力的这段时间里,最不开心的一天尽可能的开心.并且一共吃D (1 & ...

  2. Flink 中LatencyMarks延迟监控(源码分析)

    流式计算中处理延迟是一个非常重要的监控metric flink中通过开启配置   metrics.latency.interval  来开启latency后就可以在metric中看到askManage ...

  3. linux google protobuf

    说明: protobuf已经全面迁移到github,地址:https://github.com/google/protobuf 直接下载2.6.1版本:https://github.com/googl ...

  4. 3- 设置断点修改Response

    以下是借鉴别人的知识分享.我在这里转载,如有冒犯,还请告知. 只要你会设置断点修改请求内容的话,这个设置断点修改响应内容的方法也是一样的,只需要修改一下命令即可. 修改响应内容也有两种方法: 第一种: ...

  5. 介绍一款自己实现的rabbit轻量级组件和使用方法

    DotNetCore.RabbitMQ.Extensions介绍 这是一个 基于.NETStandard 2.0的Rabbit轻量级框架,可以让开发人员无需关注底层变动,专注编写业务代码,从而达到便捷 ...

  6. MySQL 04

    目录 python操作mysql mysql sql注入问题 问题描述 解决办法 增/删/改 查询 索引 基本概念 索引的原理 mysql索引种类 普通索引 唯一索引 联合索引 创建索引 正确使用索引 ...

  7. 3步轻松搞定Spring Boot缓存

    作者:谭朝红 前言 本次内容主要介绍基于Ehcache 3.0来快速实现Spring Boot应用程序的数据缓存功能.在Spring Boot应用程序中,我们可以通过Spring Caching来快速 ...

  8. 十分钟学会Markdown基本语法

    文章目录 Markdown 语法 一.标题 这是一级标题 这是二级标题 这是三级标题 这是四级标题 这是五级标题 这是六级标题 二.字体 三.引用 四.分割线 五.图片 六.超链接 七.列表 八.表格 ...

  9. 下载Abook 高等教育出版社网站资料

    一.背景 又快到了期末复习周,这个学期学了一门操作系统,老师没有给课本习题的答案,说是配套网站上有,我看了一下,确实有,是高等教育出版社的数字课程网站Abookl http://abook.hep.c ...

  10. JS---案例:点击按钮设置div背景色渐变

    案例:点击按钮设置div背景色渐变 背景色渐变:设置透明度 <div id="dv"></div> <input type="button& ...