Java中抽象类与接口的区别 | Java基础

       在Java中,abstract class和interface是支持抽象类定义的两种机制。两者在对于抽象类的支持方面具有很大的相似性,甚至可以互相替换,有些人认为在Java中可以完全用接口替换抽象类,其实不然,抽象和接口类各有长处,两者结合使用达到取长补短的目的。

       抽象类(abstract class)是位于上层更具有通用性,甚至更加抽象,抽象类是一类事物的高度聚合。从这个角度看,祖先类更加通用,人们只将它作为派生其他类的基类,而不是作为想使用的特定的实例类,从定义我们就可以看出抽象类是一种"is-a"的关系,抽象类可以包含一个或多个抽象方法(当然也可以不包含任何抽象方法),除了抽象还可包含具体数据和具体方法。凡是用abstract修饰的方法都是抽象方法,在抽象类中抽象方法不可有方法体抽象类不可以被实例化,但是可以引用一个非抽象子类的实例,抽象类中不能有抽象构造函数或抽象静态方法,Abstract 类的子类为它们父类中的所有抽象方法提供实现,否则它们也是抽象类为。但是需要引起注意的是,抽象类可以有构造方法,构造方法不可继承,但可以供子类用super()

或者super(Object... obj)调用

       接口(interface)是抽象类的变体。在接口中,所有方法都是抽象的。抽象方法默认标记为public,域默认标记为public static final,即使在声明时未加上这些关键字,java在编译过程中均会自动添加。有些接口值定义了常量,而没有定义方法。例如,标准库中有一个SwingConstants,它只包含NORTH、SOUTH和HORIZONTAL等常量,而实现SwingConstants接口的类都自动地继承了这些常量,并可以在方法中直接地引用NORTH,而不必采用SwingConstants.NORTH,这样的繁琐书写形式。另外,接口中不可以含有构造方法。

       两者之间存在许多共同之处,比如两者都不可用new运算符实例化一个对象,但均可以声明/引用变量(接口可以声明接口变量,抽象类可以声明抽象类对象)。那么两者既然有这么多共同之处,是不是就可以用抽象类完全替代接口呢?答案是否定的。我们知道与C++不同的是,Java不支持多继承,因为多继承让语言本身变得是否复杂,效率也会降低。接口可以提供多重继承的大多数好处,同时避免多重继承的复杂性和低效率。总结一下区别:

       区别一,两者表达的概念不一样。抽象类是一类事物的高度聚合,那么对于继承抽象类的子类来说,对于抽象类来说,属于“是”的关系;而接口是定义行为规范,因此对于实现接口的子类来说,相对于接口来说,是“行为需要按照接口来完成”。这些听起来有些虚,举个例子。例如,狗是对于所有狗类动物的统称,京哈是狗,牧羊犬是狗,那么狗的一般特性,都会在京哈,牧羊犬中找到,那么狗相对于京哈和牧羊犬来说,就属于这类事物的抽象类型;而对于“叫”这个动作来说,狗可以叫,鸟也可以叫。很明显,前者相当于所说的是抽象类,而后者指的就是接口。

       区别二,继承类对于两者所涉及方法的实现是不同的。继承类对于抽象类所定义的抽象方法,可以不用重写,也就是说,可以延用抽象类的方法,当对非抽象子类必须重写其方法;对于子类接口可以不重写、声明父类接口的方法,而对于接口实现类所定义的方法来说,在继承类中必须要给出所有接口相应的方法实现。

       区别三,在抽象类中,新增一个非抽象方法的话,继承类中可以不用作任何处理;而对于接口实现类来说,则需要修改继承类,提供新定义的方法。知道了两者的区别,再来说说,接口相对于抽象类的优势。

  好处一,接口不光可以作用于引用类型,也可以作用于值类型。而抽象类来说,只能作用于引用类型。

  好处二,Java的类型继承只能是单继承的,也就是说一个类型只能继承一个类型,而可以继承多个接口。其实,我对于这一点也比较赞同,多继承会使继承树变的混乱。

  好处三,由于接口只是定义属性和方法,而与真正实现的类型没有太大的关系,因此接口可以被多个类型重用。相对于此,抽象类与继承类的关系更紧密些。

  好处四,通过接口,可以减少类型暴露的属性和方法,从而便于保护类型对象。当一个实现接口的类型,可能包含其他方法或者属性,但是方法返回的时候,可以返回接口对象,这样调用端,只能通过接口提供的方法或者属性,访问对象的相关元素,这样可以有效保护对象的其他元素。

  好处五,减少值类型的拆箱操作。对于Struct定义的值类型数据,当存放集合当中,每当取出来,都需要进行拆箱操作,这时采用Struct+Interface结合的方法,从而降低拆箱操作。

  相对于抽象类来说,接口有这么多好处,但是接口有一个致命的弱点,就是接口所定义的方法和属性只能相对于继承它的类型(除非在继承类中修改接口定义的函数标示),那么对于多层继承关系的时候,光用接口就很难实现。因为如果让每个类型都去继承接口而进行实现的话,首先不说编写代码比较繁琐,有时候执行的结果还是错误,尤其当子类型对象隐式转换成基类对象进行访问的时候。

  那么这时候,需要用接口结合虚方法来实现。其实在继承中,到底使用接口还是抽象类。接口是固定的,约定俗成的,因此在继承类中必须提供接口相应的方法和属性的实现。而对于抽象类来说,抽象类的定义方法的实现,贯穿整个继承树,因此其中方法的实现或者重写都是不确定的。因此相对而言,抽象类比接口更灵活一些。

  如下给出两者的简单对比表格。

 

接口

抽象类

多继承

支持

不支持

类型限制

没有

有,只能是引用类型

方法实现

继承类型中必须给出方法实现

继承类中可以不给出

扩展性

比较麻烦

相对比较灵活

多层继承

比较麻烦,需要借助虚函数

比较灵活

以上部分内容摘自:抽象类和接口的区别

另有,从概念层面区别两者的一篇博文:详细解析Java中抽象类和接口的区别

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值