编程Java世界系统分析师

Java中的抽象类和接口的区别

2019-10-18  本文已影响0人  仲伦

本文主要列举Java语言中抽象类和接口的区别,不详细讲解接口和抽象类。


抽象类和接口.png

不知道大家有没有注意到,凡是问到某两个事物的区别,都会首先介绍它们的共同点,然后再介绍它们的区别,我们这里也不例外:

1、相同点

1.1. 接口和抽象类都不能被实例化
  public interface Flyable { // 声明接口
  }

  public abstract class Flyer { // 声明抽象类
  }

  public class InstantiateTest {
       public static void main( String[] args ){
              Flyable a = new Flyable(); // 编译错误
              Flyer b = new Flyer() ; // 编译错误
       }
  }
1.2. 接口和抽象类中都可以包含抽象方法
  public interface Flyable {
       public abstract void fly() ; // 默认都是 public abstract 所修饰
  }

  public abstract class Flyer {
       public abstract void fly() ; // 必须显式指定 abstract 修饰符
  }
1.3. 接口和抽象类中都可以包含非抽象的实例方法 ( 从Java 8 开始 )
  public interface Flyable {
       // 从 Java 8 开始可以在接口中声明 default 修饰的、非抽象的实例方法
       public default void initialize() {  

       }
  }

  public abstract class Flyer {
       //  Java 类中本类就可以声明非抽象实例方法
       public void initialize() {

       }
  }
1.4. 接口和抽象类中都可以包含类方法 ( 从Java 8 开始 )
  public interface Flyable {
       // 从 Java 8 开始可以在接口中声明类方法
       public static void prepare() {  

       }
  }

  public abstract class Flyer {
       //  Java 类中本类就可以声明类方法
       public static void prepare() {

       }
  }
1.5. 接口和抽象类中都可以包含私有方法 ( 从Java 9 开始 )
  public interface Flyable {
       // 从 Java 9 开始可以在接口中声明 private 修饰的非抽象方法
       private void ready() {  

       }

       private static void hello(){

       }
  }

  public abstract class Flyer {
       //  Java 类中本类就可以声明私有方法
       private void ready() {

       }

       private static void hello(){

       }
  }
1.6. 接口和抽象类中都可以包含常量
  public interface Flyable {
       // 接口中所有的常量默认都是 public static final 
       public static final String TYPE = "可飞行" ;
  }

  public abstract class Flyer {
       // Java 类中本来就可以声明常量 
       public static final String TYPE = "飞行物" ;
  }
1.7. 接口和接口、抽象类和其它类之间的继承都使用 extends 关键字实现
  public interface Moveable {
  }
  // 接口继承接口
  public interface Flyable extends Moveable {
  }

  public abstract class Flyer {
  }
  // 抽象类继承抽象类
  public abstract class Plane extends Flyer {
  }
  // 具体类继承抽象类
  public class Aircraft extends Flyer {
  }

接口和接口之间的继承、抽象类和抽象类之间的继承,以及抽象类和具体类之间的继承都使用 extends 关键字实现。

2、区别

2.1. 所有的抽象类都是Object类的子类,而接口则没有默认的最顶层父接口

( 注意这个区别是最重要的区别之一,凡是没有说明这一点的,都是不合适的 )

  // 除非通过 extends 关键字显式指定了接口的父接口,否则接口默认没有父接口
  public interface Flyable {
       // 接口中所有的常量默认都是 public static final 
       public static final String TYPE = "可飞行" ;
  }

  // 对于抽象类而言,若未显式使用 extends 指定其父类,则其父类为java.lang.Object类
  // 如果通过 extends 关键字显式指定了抽象类的直接父类,则其java.lang.Object类为其间接父类
  public abstract class Flyer {
  }
2.2. 抽象类只能有一个直接父类,接口可以父接口直接继承多个接口

( 注意这个区别是最重要的区别之一,凡是没有说明这一点的,都是不合适的 )

  public interface Liveable {
       void live();
  }
  public interface Moveable {
       void move();
  }
  // 接口可以一次继承多个接口
  public interface Flyable extends Moveable , Liveable {
  }

  public abstract class Flyer {
  }
  // 类只能继承一个直接父类
  public class Kites extends Flyer {
  }
  // 尝试让一个类继承多个直接父类会导致编译错误
  public class Airship extends Flyer , Object { // 编译错误
  }
2.3. 抽象类有构造方法,接口没有构造方法

( 注意这个区别是最重要的区别之一,凡是没有说明这一点的,都是不合适的 )

  public abstract class Flyer {
       public Flyer() { // 显式声明的无参构造
          super();
       }
  }

如果没有显式书写构造方法,编译器也会为抽象类添加一个公开的无参的构造方法。
抽象类中的构造方法是供其直接子类调用的,并不是为了直接创建抽象类本身的实例准备的。

  public interface Flyable {
       // 尝试为接口添加构造方法会导致编译错误
       public Flyable() { // 编译错误 
       }
  }
2.4. 接口中的成员变量只能是常量,抽象类中的成员变量可以是常量也可以是非常量

( 注意这个区别是最重要的区别之一,凡是没有说明这一点的,都是不合适的 )

  public interface Flyable {
       // 接口中所有的成员变量默认都是 public static final 修饰的
       String TYPE = "可飞行" ;  // 这里省略了 public 、static 、final 三个修饰符
       String name ; // 编译错误 ( 因为默认有 final 修饰,必须显式赋值 )
  }

  public abstract class Flyer {
       public static final String TYPE = "飞行物" ; // 常量
       private static final String ENGINE = "引擎" ; // 常量
       public static String brand ; // 类变量
       private String name ;  // 实例变量
  }
2.5. 抽象内容不同

从OOAD角度看,抽象类是对某一类事物的抽象,是设计具体类的模板(属于数据结构范畴);
接口是对行为的抽象(属于行为规范范畴),实现该接口就表示该类事物可以具有某种行为特征。

2.6. 其它区别

如果以上区别也非要当作重大区别的话,那么还可以赠送两个区别:

因为写作时间仓促,错误和不当之处是在所难免的,欢迎大家批评指正!

写作背景:
2008年被某浪删过几次博客后,后来很少写或者几乎不写博文,仅有的几篇公开的博文,也是为学生整理的学习笔记。
所以,原本不打算在简书发任何文章,仅仅作为一个看客,看看大家写的文章,必要的时点评一下,跟大家做个交流就好。
无奈最近几天看到一篇文章,标题是《接口(interface)和抽象类(abstract class)的区别是什么》,这边文章并没有抓住接口和抽象类的主要区别,因为写的挺像回事的,所以好多人继续照抄了这篇文章,导致两三天的时间里能多次看到名称相同、内容相同的文章。
将别人整理的文章为我所用是可以的,关键是你得琢磨琢磨他写的对不对,最要命的是给他们点评后,他们根本不予理会,甚至把给它们的评论直接删除了。
为了避免有更多的后来者以讹传讹,所以写了这片博文。

因为写作时间仓促,错误和不当之处是在所难免的,欢迎大家批评指正!

上一篇下一篇

猜你喜欢

热点阅读