栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

高薪程序员&面试题精讲系列14之抽象类和接口有什么区别?

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

高薪程序员&面试题精讲系列14之抽象类和接口有什么区别?

一. 面试题及剖析

1. 今日面试题

在上一篇文章中,壹哥 给大家讲解了对面向对象的理解,在面向对象里面,其实会涉及到很多内容,比如类、接口、抽象类等内容,所以面试官在这里就会问到相关问题,比如:

请说说Java中抽象类和接口有什么区别?

2. 题目剖析

这个题目,在面试初级Java程序员、实习生时,出现的频率还是挺高的。这道题目考察的还是与面向对象相关的知识点,具体是在考察我们对接口和抽象类的掌握细节,主要以记忆为主,这道题目还是比较容易回答的。对于抽象类和接口,一方面我们要记住两者的区别,另一方面我们还要明确两者各自的使用场景。

二. 参考答案

对于抽象类和接口的区别,其实没有太多深层的东西需要我们去探究,更多的还是以记忆为主,这里 壹哥 给各位设计了一个表格,清晰的对比了两者的区别。

1. 抽象类和接口常规区别

参数

抽象类

接口

使用场景

抽象类用于捕捉子类中的通用特性

接口是抽象方法的集合

默认的方法实现

可以有默认的方法实现

接口完全是抽象的。Java8之前接口方法没有默认实现,Java8开始接口方法也可以有默认实现

实现

子类使用extends关键字来继承抽象类。如果子类不是抽象类,它需要实现抽象类中所有声明的抽象方法。

子类使用implements关键字来实现接口,它需要实现接口中所有声明的未实现方法。

构造方法

抽象类可以有构造方法

接口不能有构造方法

与正常Java类的区别

抽象类不能实例化,只能用作子类的超类,其余方面和普通Java类没有任何区别

接口只是一种形式,接口自身不做任何事情

访问修饰符

抽象方法可以有public、protected和default这些修饰符,但不能用private来修饰

接口方法默认的修饰符是public,不可以使用其它修饰符。

main方法

抽象类中可以有main方法,并且我们可以运行

接口中也可以有main方法,但一般不会在接口中编写main方法。

static静态方法

抽象类中可以有static静态方法

Java8及之后,接口中也可以有static静态方法

多继承

抽象类可以继承一个类和实现多个接口

接口可以继承一个或多个其它接口

执行速度

抽象类比接口速度快

接口稍微有点慢的,因为它需要时间去匹配在子类中实现的具体方法。

添加新方法

如果在抽象类中添加了新的方法,我们可以在抽象类中给该方法提供默认的实现,因此不需要改变子类中的代码。

如果在接口中添加方法,那么实现了该接口的子类也需要改变代码。

以上表格中就是抽象类与接口的主要区别,我们面试时,挑拣几个重要的区别说说就可以了。

2. 抽象类和接口使用场景的区别

我们再次从抽象类和接口的使用场景方面,来分析对比两者之间的区别。

  • 如果我们想在多个子类中都做同一件事,即抽取出子类的共同特性,但这件事每个类中的具体实现细节又不同时,就可以考虑使用抽象类。比如我们每个人都要找一个对象,但是每个人找的对象又不一样。
  • 如果我们想实现多继承,就必须使用接口,因为Java不支持多继承,子类不能继承多个父类,但可以实现多个接口。

3. Java单继承的原因

在上面的小节中,我提到了Java中的类是单继承、多实现的,那为什么这样呢?

这是因为,当子类重写父类方法的时候,或者隐藏父类的成员变量以及静态方法的时候,JVM会使用不同的绑定规则。如果一个类有多个直接的父类,那么会使绑定规则变得更复杂。为了简化软件的体系结构和绑定机制,所以Java语言禁止多继承。

而接口却可以多继承,是因为接口中只有抽象方法,没有静态方法和非常量的属性,只有接口的实现类才会重写接口中方法。因此一个类有多个接口也不会增加JVM的绑定机制和复杂度。

4. 从设计目的分析两者的区别

接着我们再从接口和抽象类的设计目的来分析,两者之间有什么区别,其实这个角度更接近于两者的本质区别。

接口的设计目的,更多的是对类的行为进行约束。因为接口中不能规定子类不可以有什么行为,也就是说接口其实是提供了一种机制,可以强制要求不同的类具有相同的行为。接口约束了行为的有无,但不对如何实现行为进行限制。

抽象类的设计目的,既可以提高代码的复用性,又能达到个性化的目的。当不同的类具有某些相同的行为,且其中一部分行为的实现方式一致时,可以让这些类都继承自一个抽象类。比如我们可以在抽象类中实现所有子类都具有的共同方法A,避免让所有的子类都来实现这个A方法,这就达到了代码复用的目的。然后这时还可以在抽象类中定义一个抽象方法B,留给各个子类自己去实现,这样又达到了个性化的目的。

三. 代码案例

为了方便各位加深对接口和抽象类区别的理解,壹哥 给各位编写了一个案例,希望能对你有所启发。

我们首先来设计一个产品需求,比如有这么一个例子:

每个人都具有 eat() 、sleep() 两个功能方法,这时候我们其实可以分别通过接口和抽象类来定义这个抽象概念。

//接口
public interface IPerson {

      
    void eat();

      
    void sleep();

}

//抽象类
public abstract class AbstractPerson {
      
    public abstract void eat();

      
    public abstract void sleep();
}

但是如果我们现在需要让人拥有一项特殊的技能——开飞机 drivePlane(),这时如何增加这个行为呢?首先我们思考一下:

  1. 将开飞机这个方法与前面两个方法一同写入到抽象类中,你觉得这样合适吗?如果是这样,但凡继承这个抽象类的人都具有了开飞机的技能,明显不合适吧。
  2. 将开飞机的方法与前面两个方法一同写入到接口中,当需要使用开飞机功能的时候,也必须实现接口中的eat()、sleep()方法,这显然也不合适。

那么该如何解决这个问题呢 ? 我们可以仔细想一想,eat和sleep都是人类本身所具有的一种行为,而开飞机这种行为则是后天训练出来的,只能算是对人类的一种附加或者延伸, 两者不应该在同一个范畴内。所以我们考虑将这个单独的行为,独立的设计一个接口,其中包含drivePlane()方法,可以将Person设计为一个抽象类, 其中包括eat()、sleep() 方法。

所以根据上面的需求,壹哥 把代码更改如下:

//接口中定义特殊功能
public interface IPerson {
    
    void drivePlane();
}

//抽象类中还是和之前一样
public abstract class AbstractPerson {
    
    public abstract void eat();

    
    public abstract void sleep();

}

//定义子类拥有特殊功能

public class Pilot extends AbstractPerson implements IPerson{
    
    @Override
    public void eat() {
        System.out.println("飞行员开始吃...");
    }

    @Override
    public void sleep() {
        System.out.println("飞行员开始睡...");
    }

    @Override
    public void drivePlane() {
        System.out.println("飞行员开飞机...");
    }
    
}

通过上面的这个案例,你现在是否明白什么时候该用抽象类,什么时候该用接口了吗?其实我们只需要明白,继承属于 "是不是" 的关系,而 接口 实现则是 "有没有"的关系。如果一个类继承了某个抽象类,则该类必定是这个抽象类的同一种类;而接口实现则是有没有、具备不具备的关系,比如人是否具备开飞机的能力,能则可以实现这个接口,不能就不实现这个接口。

三. 结论

我在上面给各位讲解了抽象类和接口的各种区别,并且通过代码案例讲解了该在什么情况下选择抽象类和接口,最后我再给各位简单梳理一下两者的相同点及不同点。

1. 接口和抽象类的共同点如下:
  1. 两者都属于上层的抽象层;
  2. 两者都不能被实例化;
  3. 两者都能包含抽象的方法,这些抽象的方法都用于描述类具备的功能,但是不必提供具体的实现。

2. 接口和抽象类的区别如下:

1. 在抽象类中可以有非抽象方法,从而避免在子类中重复书写这些方法,这样可以提高代码的复用性,这是抽象类的优势;Java8之前,接口中只能有抽象的方法,Java8之后接口中也可以有默认实现。
2. 一个类只能继承一个直接父类,这个父类可以是具体的类也可是抽象类;但是一个类可以实现多个接口。

......

至此,壹哥 就给各位总结了接口与抽象类的区别,不知道你是否还有别的见解呢?可以在评论区留言讨论哦。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/351560.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号