当前位置: 首页 > news >正文

抽象类和接口的区别

一、基本定义

  • 抽象类(abstract class)
    • 一种不能被实例化的类,用来被子类继承。
    • 可以包含 抽象方法(没有方法体,需要子类实现)和 具体方法。
    • 适用于描述“is-a”关系(是一种)。
  • 接口(interface)
    • 一种更纯粹的抽象定义,规定了一组方法的“契约”。
    • Java 8 之前只能有抽象方法;Java 8+ 支持 default 方法、static 方法,Java 9+ 支持 private 方法。
    • 适用于描述“has-a”或“can-do”关系(能做什么)。

二、主要区别(对比表)

对比点

抽象类

接口

关键字

abstract class

interface

继承/实现

子类用extends,单继承

类用 implements,多实现

成员变量

可以有实例变量(普通字段)

只能有静态常量(public static final)

方法

可以有抽象方法 + 普通方法

默认方法全是public abstract(Java8 起支持default/static方法)

构造方法

可以有构造方法(但不能直接实例化)

不能有构造方法

访问修饰符

抽象方法可以是 public/protected

方法默认 public abstract,不能是protected/private

继承限制

只能单继承一个抽象类

可以实现多个接口

设计层面

模板,提供“基础实现”

纯契约,强调“能力”扩展

实例化区别

对比点

接口(interface)

抽象类(abstract class)

能否直接 new

不能直接new

不能直接new

方式 1:实现类

通过implements实现类实例化PayService pay = new AliPayService();

通过 extends 子类实例化 Animal dog = new Dog();

方式 2:匿名内部类

PayService pay = new ayService() { public void pay(double a){...} };

Animal cat = new Animal() { void sound(){...} };

方式 3:Lambda 表达式

仅限函数式接口Runnable r = () -> {...};

不支持(因为可能有多个抽象方法)

方式 4:动态代理

常见于 Spring AOP / MyBatis Proxy.newProxyInstance(...);

一般不用动态代理(框架里常用工厂模式)

方式 5:框架工厂/模板方法

通过 IOC 容器注入接口代理类(Spring Service Bean)

通过工厂方法返回子类实例(SpringAbstractApplicationContext)

本质

依靠实现类才能有对象

依靠子类才能有对象

接口:靠“实现类” + “匿名类” + “Lambda” + “动态代理”。

抽象类:靠“子类” + “匿名类” + “工厂模式”。

共同点:都不能直接 new,必须依赖子类/实现类。

三、使用场景

抽象类适用场景

  • 当类之间存在强烈的继承关系,有 共享的字段和方法。
  • 父类提供 部分默认实现,子类只需实现差异化部分。
  • 示例:Spring 中的 HttpServlet,它是抽象类,提供了很多默认实现,子类只需实现 doGet / doPost。
public abstract class Animal {String name;public void eat() { System.out.println("eating..."); }public abstract void sound();
}public class Dog extends Animal {@Overridepublic void sound() { System.out.println("Bark"); }
}

接口适用场景

  • 当需要定义一种 行为规范,不同类可以有不同的实现。
  • 常用于 解耦,强调“能做什么”而不是“是什么”。
  • 示例:Spring 中的 BeanFactory、ApplicationContext 都是接口,不同实现类(如 XmlApplicationContext、AnnotationConfigApplicationContext)可以自由扩展。
public interface PayService {void pay(double amount);
}public class AliPayService implements PayService {@Overridepublic void pay(double amount) { System.out.println("AliPay: " + amount); }
}public class WeChatPayService implements PayService {@Overridepublic void pay(double amount) { System.out.println("WeChatPay: " + amount); }
}

四、总结

  • 抽象类:是一种 模板,强调 继承,可以有状态(成员变量)。
  • 接口:是一种 契约,强调 规范,只能定义能力(方法)。
  • 项目中:
    • 抽象类 → 用来封装一类事物的通用逻辑。
    • 接口 → 用来定义规范,解耦调用方和实现方。
举例对比:
  • “动物”是一个抽象类,因为它有共同属性和部分方法(名字、吃饭)。
  • “会飞的东西”是一个接口,因为鸟、飞机、超级英雄都能实现“Flyable”,但它们并没有统一的父类。
http://www.lryc.cn/news/625147.html

相关文章:

  • VLN视觉语言导航(3)——神经网络的构建和优化 2.3
  • qsort函数使用及其模拟实现
  • Android Cutout(屏幕挖孔)详解
  • SpringBoot--Spring MVC 拦截器注入与 new 的区别
  • gdb的load命令和传给opeocd的monitor flash write_image erase命令的区别
  • 优秀开发者的重要认知能力无法被AI替代
  • 在win10/11下Node.js安装配置教程
  • Ai Agent 项目
  • 项目延期的主要原因分析,以及应对策略
  • 摔倒检测数据集:1w+图像,yolo标注
  • 深度学习-计算机视觉-微调 Fine-tune
  • 【完整源码+数据集+部署教程】织物缺陷检测系统源码和数据集:改进yolo11-RevCol
  • STL库——string(类函数学习)
  • steal tsoding‘s pastebeam code as go server
  • CMake指令:查找文件(find_file)、查找目录(find_path)、查找库文件(find_library)
  • npm设置了镜像 pnpm还需要设置镜像吗
  • Esp32基础(③旋转编码器)
  • wait / notify、单例模式
  • 在openEuler系统中如何查看文件夹下每个文件的大小
  • AVB(Android Verified Boot)中vbmeta结构浅析
  • C/C++ 中 str、str、*str 在指针语境下的具体含义(以 char* str 为例):
  • Android输入框文字不垂直居中
  • Linux下的软件编程——IPC机制
  • Java发送企业微信通知
  • Vue2篇——第五章 Vue.js 自定义指令与插槽核心
  • (第十八期)图像标签的三个常用属性:width、height、border
  • minio安装和配置
  • 【DL学习笔记】交叉熵损失函数详解
  • 之前说的要写的TCP高性能服务器,今天来了
  • 给linux的root磁盘扩容