Java SE 抽象类与接口:abstract class 和 interface 对比详解
本文面向 Java 初学开发者、正在准备面试的同学帮大家理清抽象类和接口的核心区别、使用场景解决很多人容易混淆的「什么时候该用抽象类什么时候该用接口」这个问题同时配套可直接运行的示例代码。一、前置认知为什么需要抽象在面向对象编程中我们会对一类事物抽取共性。有些父类本身不适合直接实例化它只用来定义规范、抽取公共代码这就是抽象的来源。Java 中提供两种机制实现抽象规范定义abstract class抽象类和interface接口二者设计目标不同语法限制也不一样。二、抽象类 abstract class2.1 基础语法被abstract修饰的类叫做抽象类。抽象类不能直接 new 实例化可以包含普通成员变量、普通成员方法、静态方法、构造方法可以包含抽象方法只有方法声明没有方法体同样用abstract修饰子类继承抽象类extends必须实现所有抽象方法子类自身也标记为 abstract 时可以不实现示例代码/** * 动物抽象类 * author 技术学习笔记 */abstractclassAnimal{// 普通成员变量protectedStringname;// 抽象类拥有构造方法供子类调用publicAnimal(Stringname){this.namename;}// 普通方法子类可以直接复用publicvoidsleep(){System.out.println(name 正在睡觉);}// 抽象方法没有方法体交给子类实现publicabstractvoidshout();}// 子类继承抽象类实现抽象方法classDogextendsAnimal{publicDog(Stringname){super(name);}Overridepublicvoidshout(){System.out.println(name汪汪汪);}}publicclassAbstractDemo{publicstaticvoidmain(String[]args){AnimaldognewDog(小黑);dog.sleep();dog.shout();}}2.2 抽象类的特点总结使用extends继承Java 是单继承一个类只能继承一个抽象类兼顾「代码复用」和「规范定义」公共逻辑写在抽象类普通方法中可以有构造器、成员变量权限修饰符和普通类一致三、接口 interfaceJava 8 对接口做了重要升级引入默认方法default和静态方法Java 9 之后还支持私有方法。很多老教程只讲抽象方法容易造成理解偏差。3.1 基础语法接口使用interface定义类通过implements实现接口。接口不能实例化Java 8 之前接口里的方法默认是public abstract抽象方法Java 8支持default默认方法带方法体、static静态方法Java 9支持private私有方法供接口内部复用逻辑接口中的变量默认是public static final也就是常量示例代码/** * 可跑动接口 * author 技术学习笔记 */interfaceRunable{// 常量默认 public static finalintMAX_SPEED120;// 抽象方法实现类必须重写voidrun();// Java 8 default 默认方法有默认实现实现类可以选择重写defaultvoidshowInfo(){System.out.println(最大奔跑速度上限MAX_SPEED);}// Java 8 static 静态方法通过接口名直接调用staticvoidwelcome(){System.out.println(奔跑能力接口);}}// 实现类可以同时实现多个接口classRabbitimplementsRunable{Overridepublicvoidrun(){System.out.println(兔子快速奔跑);}}publicclassInterfaceDemo{publicstaticvoidmain(String[]args){Runable.welcome();RunablerabbitnewRabbit();rabbit.run();rabbit.showInfo();}}3.2 接口的特点总结一个类可以implements多个接口突破单继承限制核心定位定义行为规范侧重「能做什么」而不是「是什么」接口优先轻量化设计一般不存储可变成员变量只存放常量四、抽象类 和 接口 核心对比表对比项abstract class 抽象类interface 接口关键字extends 继承implements 实现继承数量单继承只能继承一个多实现可以实现多个构造方法有构造方法供子类初始化没有构造方法成员变量可以有普通变量、静态变量只能是 public static final 常量方法普通方法、抽象方法、静态方法抽象方法、default、static、private 方法设计思想is-a属于同一个事物体系复用代码has-a / can-do具备某种行为能力五、开发中怎么选如果多个子类之间有大量公共代码需要复用属于「is-a」从属关系优先用抽象类。例如动物、交通工具。如果只是给不同类附加一套行为规范类之间没有继承关系想要多套能力叠加优先用接口。例如可奔跑、可序列化、可比较。推荐组合写法抽象类负责主干公共代码接口负责扩展行为规范兼顾复用与扩展。经典例子ArrayList继承AbstractList抽象类复用集合基础逻辑同时实现List、RandomAccess等多个接口定义行为规范。六、常见坑点抽象类的构造方法不是用来 new 抽象类是给子类super()调用接口的 default 方法如果出现多接口同名冲突实现类必须手动重写该方法接口里变量自动是常量尝试修改会编译报错抽象方法不能有方法体abstract和private、static、final不能同时修饰方法。