接口和抽象类的区别与使用场景
前言:
前几天面试的是面试官问了一个问题
接口和抽象类了解吧?
说一下 他们的分别用在什么场景下(就是让说一下我该如何选择使用接口还是抽象类)
我回答的不忍直视。
我事后问了一个同学,你给我来了一句那要看业务
我不知道看业务吗,我想知道的是啥业务用接口啥业务用抽象类
吐槽完毕开始正题
Java基础之接口与抽象类的区别
Java中接口和抽象类的定义语法分别为interface与abstract关键字。
抽象类: 在Java中被abstract关键字修饰的类称为抽象类,被abstract关键字修饰的方法称为抽象方法,抽象方法只有方法的声明,没有方法体。抽象类的特点:
a、抽象类不能被实例化只能被继承;
b、包含抽象方法的一定是抽象类,但是抽象类不一定含有抽象方法;
c、抽象类中的抽象方法的修饰符只能为public或者protected,默认为public;
d、一个子类继承一个抽象类,则子类必须实现父类抽象方法,否则子类也必须定义为抽象类;
e、抽象类可以包含属性、方法、构造方法,但是构造方法不能用于实例化,主要用途是被子类调用。
接口:Java中接口使用interface关键字修饰,特点为:
a、接口可以包含变量、方法;变量被隐士指定为public static final,方法被隐士指定为public abstract(JDK1.8之前);
b、接口支持多继承,即一个接口可以extends多个接口,间接的解决了Java中类的单继承问题;
c、一个类可以实现多个接口;
d、JDK1.8中对接口增加了新的特性:(1)、默认方法(default method):JDK 1.8允许给接口添加非抽象的方法实现,但必须使用default关键字修饰;定义了default的方法可以不被实现子类所实现,但只能被实现子类的对象调用;如果子类实现了多个接口,并且这些接口包含一样的默认方法,则子类必须重写默认方法;(2)、静态方法(static method):JDK 1.8中允许使用static关键字修饰一个方法,并提供实现,称为接口静态方法。接口静态方法只能通过接口调用(接口名.静态方法名)。
1.基本概念和声明
1.1抽象类
抽象类是特殊的类,只是不能被实例化,天生就是要被继承的;除此以外,具有类的其他特性;重要的是抽象类可以包括抽象方法,这是普通类所不能的。抽象方法只能声明于抽象类中,且不包含任何实现,派生类必须覆盖它们。另外,抽象类可以派生自一个抽象类,可以覆盖基类的抽象方法也可以不覆盖,如果不覆盖,则其派生类必须覆盖它们
抽象方法必须用abstract关键字进行修饰。如果一个类含有抽象方法,则称这个类为抽象类,抽象类必须在类前用abstract关键字修饰。
一个简单的声明
public abstract class Door { //定义抽象类private String brand;//品牌private double price;//价格public abstract void open();public abstract void close();public String getBrand() {return brand;}public void setBrand(String brand) {this.brand = brand;}public double getPrice() {return price;}public void setPrice(double price) {this.price = price;}
}
包含抽象方法的类称为抽象类,但并不意味着抽象类中只能有抽象方法,它和普通类一样,同样可以拥有成员变量和普通的成员方法。注意,抽象类和普通类的主要有三点区别:
1)抽象方法必须为public或者protected(因为如果为private,则不能被子类继承,子类便无法实现该方法),缺省情况下默认为public。
2)抽象类不能用来创建对象;
3)如果一个类继承于一个抽象类,则子类必须实现父类的抽象方法。如果子类没有实现父类的抽象方法,则必须将子类也定义为为abstract类。
1.2接口
接口,英文称作interface,在软件工程中,接口泛指供别人调用的方法或者函数。从这里,我们可以体会到Java语言设计者的初衷,它是对行为的抽象。在Java中,定一个接口的形式如下:
public interface Alarm {public static final String effect ="提醒/警告";//相当于常量void alarm();default void alarmMode(){System.out.println("叫");};
}
接口中可以含有 变量和方法。但是要注意,接口中的变量会被隐式地指定为public static final变量(并且只能是public static final变量,用private修饰会报编译错误),而方法会被隐式地指定为public abstract方法且只能是public abstract方法(用其他关键字,比如private、protected、static、 final等修饰会报编译错误),并且接口中所有的方法不能有具体的实现,也就是说,接口中的方法必须都是抽象方法(特别提醒1.8后接口也有可以非抽象方法了
但是要用 default修饰的方法)。从这里可以隐约看出接口和抽象类的区别,接口是一种极度抽象的类型,它比抽象类更加“抽象”,并且一般情况下不在接口中定义变量。
1.3 应用场景介绍
什么时候使用抽象类和接口?
如果拥有一些方法并且想让它们中的一些有默认实现,那么使用抽象类吧。
对用一类事物共有的方法可以定义成抽象方法场景: 如 AbstractQueuedSynchronize 这个抽象类 继承这个类的时候你不用考虑线程的插入排队和休眠 只需要考虑获取的实现就行如果你是定义成接口的话 所有的 方法都需要你去自己实现 (那些CAS的方法和线程等待的方法是可以共用的)
如果想实现多重继承,那么必须使用接口。由于Java不支持多继承,即一个类 只能有一个超类。但是,可以实现多个接口,因此可以使用接口来解决它。
有以下一个场景我想声明一个接口或者抽象类 但是要继承这个类子类的之类已经有父类则个时候就不能在声明抽象类了(就算声明了你也用不了)
如果基本功能在不断改变,那么就需要使用抽象类,达到解耦目的。如果不断改变基本功能并且使用接口,那么就需要改变所有实现了该接口的类。
这种一般是在项目初期才会出现吧 因为开闭原则:软件实体应当对扩展开放,对修改关闭。 (在理想的状态下,当我们需要为一个软件系统增加新功能时, 只需要从原来的系统派生出一些新类就可以,不需要修改原来的任何一行代码。)
接口更多的是在系统架构设计方面发挥作用,主要用于定义模块之间的通信契约。而抽象类在代码实现方面发挥作用,可以实现代码的重用。例如,模板方法设计模式就是抽象类的一个典型应用,假设某个项目的所有HTTP请求都要用相同的方式进行权限判断、访问日志记录和异常处理,那么就可以定义一个抽象的基类,让所有的controller都继承这个抽象基类,在抽象基类的service方法中实现上述功能,在各个子类中只是完成各自的业务逻辑代码,伪代码如下:
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; public abstract class BaseServlet extends HttpServlet {public final void service(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {// 记录访问日志// 进行权限判断
} protected abstract void doService(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException;// 注意访问权限定义成protected,显得既专业,又严谨,因为它是专门给子类用的} class MyServlet1 extends BaseServlet {protected void doService(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {// 本Servlet只处理的具体业务逻辑代码}}
基类方法中间的某段代码不确定,留给子类去实现。
1.4 举例说明
下面看一个网上流传最广泛的例子——门和警报——门都有open()和close( )两个动作,通过抽象类和接口来定义这个抽象概念。
public abstract class Door { //定义抽象类private String brand;//品牌private double price;//价格public Door() {}public Door(String brand, double price) {this.brand = brand;this.price = price;}public abstract void open();//抽象开门方法public abstract void close();//抽象关门方法public String getBrand() {return brand;}public void setBrand(String brand) {this.brand = brand;}public double getPrice() {return price;}public void setPrice(double price) {this.price = price;}
}
但是现在如果需要门具有报警alarm()的功能,那么该如何实现?下面提供两种思路:
- 将这三个功能都放在抽象类里面,但是这样一来所有继承于这个抽象类的子类都具备了报警功能,但是有的门并不一定具备报警功能;
- 将这三个功能都放在接口里面,需要用到报警功能的类就实现接口中的open()和close(),也许这个类根本就不具备open()和close()功能,比如火灾报警器。
从这里可以看出,Door的open()、 close()和alarm()根本就属于两个不同范畴内的行为,open()和close()属于门本身固有的行为特性,而alarm)属于延伸的附加行为。因此最好的解决办法是单独将报警设计为一个接口,包含alarm()行为,Door设计为单独的一个抽象类,包含open和close两种行为。再设计一个报警门继承Door类和实现Alarm接口。
public interface Alarm {public static final String effect ="提醒/警告";void alarm();default void alarmMode(){System.out.println("叫");};
}
public abstract class Door { //定义抽象类private String brand;//品牌private double price;//价格public Door() {}public Door(String brand, double price) {this.brand = brand;this.price = price;}public abstract void open();//抽象开门方法public abstract void close();//抽象关门方法public String getBrand() {return brand;}public void setBrand(String brand) {this.brand = brand;}public double getPrice() {return price;}public void setPrice(double price) {this.price = price;}
}public class SecurityDoor extends Door implements Alarm {public SecurityDoor() {}public SecurityDoor(String brand, double price) {super(brand, price);}@Overridepublic void open() {System.out.println("64位加密密码开启");}@Overridepublic void close() {System.out.println("三层防盗依次关闭");}@Overridepublic void alarm() {System.out.println("默认开启报警");}
}
1.5 常见问题
以下来自网图
接口和抽象类的区别与使用场景相关推荐
- C# 接口和抽象类的区别和使用场景
C# 中的接口和抽象类都是面向对象编程中常见的概念,它们都可以用于定义一组方法和属性,但是它们之间有很多的区别和使用场景. 接口和抽象类都可以被继承,接口和抽象类中的方法和属性都可以被继承和实现.但是 ...
- 【学习Day5】接口和抽象类的区别、作用和使用场景
目录 一.接口和抽象类的区别? 二.接口和抽象类的作用? 三.接口和抽象类的使用场景? 一.接口和抽象类的区别? 抽象类用abstract 来修饰 接口用interface修饰 抽象类中有构造器 接口 ...
- python接口和抽象类的区别_接口和抽象类有什么区别?
最近团队在招人:阿里新零售事业群CBU技术部招Java高级&专家,团队主要负责B2B工业品牌业务,坐标杭州滨江,有兴趣的小伙伴私戳我. **************************** ...
- java 关注公众号没有调接口_高频面试题:接口和抽象类的区别
作为一个基础的Java高频面试题,是所有Java面试者必须烂熟于心的.当然不能死记硬背,可以通过实际地写几个小demo,边实际操作边理解,既能感受到编程的快乐,更重要的是真的理解记住了二者的区别. 此 ...
- Java接口学习(接口的使用、简单工厂、代理模式、接口和抽象类的区别)
前言引入 官方解释:Java接口是一系列方法的声明,是一些方法特征的集合,一个接口只有方法的特征没有方法的实现,因此这些方法可以在不同的地方被不同的类实现,而这些实现可以具有不同的行为(功能). 我的 ...
- 接口与抽象类的区别和联系
接口 1.因为java不支持多重继承,所以有了接口,一个类只能继承一个父类,但是可以实现多个接口,同时接口本身也可以继承多个接口. 2.接口里面的成员变量默认是public static final类 ...
- 接口和抽象类的区别?
接口和抽象类的区别? 我先来说说它们俩在语法上的区别吧,然后再来谈谈我的个人理解. 抽象类可以有具体的方法和属性, 接口只能有抽象方法和常量. 抽象类使用abstract修饰,接口使用interfa ...
- 【转载】接口和抽象类的区别 --相信你看完不会再混淆了
原文地址:http://www.cnblogs.com/huihui-gohay/archive/2009/12/13/1623070.html 我想,对于各位使用面向对象编程语言的程序员来说,&qu ...
- 接口与抽象类的区别,为什么要用接口,抽象类不香吗?
接口是一种比较特殊的抽象类(个人理解) 接口与抽象类的区别: 最直观来说: 接口: 接口中变量是常量,所以接口中不能有构造方法.因为构造方法最大的作用是给对象赋值或改值(个人理解)和创建对象.因为变量 ...
最新文章
- 【错误记录】OD 调试器附加进程时找不到进程 ( CE 工具可以附加进程 )
- BP人工神经网络的介绍与实现
- 201024阶段二Linux
- Android meta作用,Android中meta-data的使用
- android 设备占用_如何查看正在占用Android设备的空间
- python:继承日志模块生成自定义日志
- P2183 [国家集训队]礼物(扩展卢卡斯)
- 邮箱如何秘密发送多个人邮件_如何发送秘密消息
- 数据vs.算法,究竟谁更重要
- dj鲜生-28-登陆验证父类的使用-Mixin类的定义
- Java Web学习笔记11:JSTL与EL
- 全球品牌百强榜单出炉:中国品牌仅有华为上榜
- php要怎么使用imagettftext_燃气灶漏气怎么办?使用天然气、液化气要注意什么?...
- 开源任务式问答机器人框架系列之Dialogflow
- 计算机应用技术Word文档题目,计算机应用技术复习题(word版)
- iOS之加速计、陀螺仪(UIAccelermeter、Core Motion)
- VC实现:bmp转jpg、jpg转bmp、截屏保存jpg
- COMSOL建立简单多面体
- 移动宽带安装说明一(刘欣)
- IC面试常考题 Verilog三分频电路设计(占空比50%,三分之一,三分之二)
热门文章
- DeepExposure: Learning to Expose Photos with Asynchronously Reinforced Adversarial Learning【论文阅读札记】
- 做女人,真好!一个男程序员的妇女节真实感悟
- 第三天 hadoop文件系统
- 关联规则挖掘——Apriori算法的基本原理以及改进
- 瞪羚企业和独角兽区别是什么?
- Win10广告过多让人反感 外媒炮轰后微软改进了
- Python打开指定浏览器的指定网页
- 模糊+滑膜轨迹跟踪控制算法 算法可实现功能:跟踪双移线,单移线,多项式曲线等多种轨迹,稳定性和较好
- vmp版本某数后缀(10-6,js逆向)
- JAVA面试灵魂108问(三十六)---实战那些事儿2