行业资讯 2025年08月6日
0 收藏 0 点赞 706 浏览 3291 个字
摘要 :

文章目录 1. 抽象类 2. 接口 3. 抽象类实现接口 4. 抽象类 vs 接口的区别 5. 何时使用? 5.1. 使用抽象类添加部分行为 5.2. 仅用于契约的接口 6. Java 8 中的接口默认……




  • 1. 抽象类
  • 2. 接口
  • 3. 抽象类实现接口
  • 4. 抽象类 vs 接口的区别
  • 5. 何时使用?
    • 5.1. 使用抽象类添加部分行为
    • 5.2. 仅用于契约的接口
  • 6. Java 8 中的接口默认方法
  • Java 8中抽象类和接口的区别

抽象类与接口是Java API 的两个主要构建模块。本文将讨论接口与抽象类之间最显著的区别。

1. 抽象类

简单来说,抽象类是通过使用关键字 abstract 声明的类。它可能包含或不包含任何抽象方法。

在下面的示例中,TestAbstractClass 包含两个方法,第一个方法是抽象的,而第二个方法是普通方法。

public abstract class TestAbstractClass {
    public abstract void abstractMethod();
    public void normalMethod()  { ... method body ... }
}

请注意,如果在类中有一个抽象方法,我们必须将类本身声明为抽象类。抽象方法使得类不完整,因此编译器要求将整个类声明为抽象的。

JVM将抽象类识别为未定义其完整行为的不完整类。声明类为抽象类只强制执行一件事:我们不能创建此类的实例。

那么为什么要创建一个根本不能实例化的类呢?答案在于它在解决一些关键的设计问题时的用途。

在应用程序中使用抽象类的唯一方法是扩展该类。如果未再次声明为抽象,那么它的子类可以实例化。

class ChildClass extends TestAbstractClass {
  @Override
  public void abstractMethod() {
    //method body
  }
}

2. 接口

接口是大多数 Java API 的另一个基本构建模块。接口定义了实现类需要遵守的契约。这些契约本质上是未实现的方法。Java 已经有一个用于未实现方法的关键字,即 `abstract`。在 Java 中,一个类可以实现任何公共接口,因此接口中声明的所有方法都需要是public的。

public interface TestInterface {
    void implementMe();
}

在上面的示例中,任何实现类都需要覆盖 implementMe() 方法。

public class TestMain implements TestInterface {
    @Override
    public void implementMe() {
        //...
    }
}

3. 抽象类实现接口

只有一种情况下我们实现接口但不重写其方法,即将类本身声明为抽象。由于 AbstractClass 是抽象的且不能被初始化,因此类的完整性没有被破坏。

public abstract class AbstractClass implements TestInterface {
    //不需要重写 implementMe()
}

当一个类继承上述的 AbstractClass 时,它必须重写 implementMe() 方法,以使自身成为一个完整的类。

public class ChildClass extends AbstractClass {
    @Override
    public void implementMe() {
        //...
    }
}

4. 抽象类 vs 接口的区别

让我们总结一下抽象类和接口之间的区别,以便进行快速回顾:

  • 接口中的所有方法都默认为公共和抽象。我们无法通过减少方法的访问权限来覆盖这种行为,甚至无法声明静态方法。只允许公共和抽象方法。而抽象类在声明方法时更加灵活。我们可以使用受保护的访问权限定义抽象方法。此外,我们还可以定义静态方法,只要它们不是抽象的。非抽象的静态方法是允许的。
  • 接口除了默认方法外,不能有完全定义的方法。根据定义,接口旨在提供唯一的契约。抽象类可以有非抽象方法,没有任何限制。
  • 子类只能继承一个父类,但可以实现任意数量的接口。这种特性通常被称为 Java 中多继承的模拟。
  • 接口是绝对抽象的,不能被实例化;Java 抽象类也不能被实例化,但如果存在 main() 方法,可以被调用。

5. 何时使用?

永远记住,接口和抽象类的选择不是二选一的,在没有适当分析的情况下,选择任何一个都会产生相同的结果。在了解了手头的问题之后,必须非常明智地做出选择。让我们来了解一些相关信息。

5.1. 使用抽象类添加部分行为

抽象类允许你定义一些行为,使它们成为应用程序框架内的优秀候选项。

让我们以 HttpServlet 为例。如果您正在使用 Servlets 技术开发 Web 应用程序,那么这是您必须继承的主要类。正如我们所知,每个 Servlet 都有明确的生命周期阶段,即初始化、服务和销毁。如果我们每次创建一个 Servlet,都必须一次又一次地编写关于初始化和销毁的相同代码,那会很痛苦。

JDK 设计人员通过将 HttpServlet 声明为抽象类来解决这个问题。它已经预先编写了有关初始化 Servlet 及其销毁的所有基本代码。您只需要重写某些方法,在其中编写与应用程序处理相关的代码,就这么简单。有意义,对吧!

你能使用接口添加上述功能吗?即使可以,对于大多数无辜的程序员来说,这种设计将会非常混乱。

5.2. 仅用于契约的接口

现在,让我们来看看接口的用法。接口只提供契约,由实现类负责实现每个单独的契约。

接口最适合的情况是,您只想定义类的特性,并希望强制所有实现实体实现这些特性。

我想以集合框架中的 Map 接口为例。它仅提供规则,即地图在实践中应该如何工作。例如,它应该存储键-值对,应该能够使用键访问值等。这些规则以接口中的抽象方法形式存在。

所有实现类(例如 HashMapHashTableTreeMapWeakHashMap)都以不同的方式实现所有方法,从而展示与其他实现类不同的特性。

此外,接口还可用于定义责任的分离。例如,HashMap 实现了 3 个接口:MapSerializableCloneable。每个接口定义了独立的责任;因此,实现类可以选择要实现的内容,并提供有限的功能。

6. Java 8 中的接口默认方法

在 Java 8 中,您现在可以在接口中定义方法。这些被称为默认方法。默认方法使您可以向库的接口添加新功能,并确保与为旧版本接口编写的代码具有二进制兼容性。

顾名思义,Java 8 中的默认方法只是默认方法。如果您不对其进行覆盖,它们就是调用类将调用的方法。

public interface Moveable {
    default void move(){
        System.out.println(\"I am moving\");
    }
}

在上面的例子中,Moveable 接口定义了一个 move() 方法,并且还提供了一个默认实现。如果任何类实现了这个接口,那么它就不需要再实现自己版本的 move() 方法。它可以直接调用 instance.move()

public class Animal implements Moveable {
    public static void main(String[] args){
        Animal tiger = new Animal();
        tiger.move();   //I am moving
    }
}

如果该类希望自定义行为,那么它可以提供自己的自定义实现并重写这个方法。现在将会调用它自己的自定义方法。

public class Animal implements Moveable {
    public void move(){
        System.out.println(\"I am running\");
    }
    public static void main(String[] args){
        Animal tiger = new Animal();
        tiger.move();   //I am running
    }
}

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

自从Java 8以来,我们可以使用默认方法在接口中提供部分实现,就像抽象类一样。因此,接口和抽象类之间的界限变得非常模糊。它们现在几乎提供了相同的功能。

然而,一个重要的区别仍然存在,那就是我们不能同时扩展多个类,而可以实现多个接口。除了这个区别之外,您可以通过接口实现与抽象类可能实现的任何功能,反之亦然。

希望您在Java中的接口和抽象类方面找到了足够的信息。

归属教程 Java基础教程

文章目录 前言  第1章 Java语言基础 第2章 流程控制语句 第3章 面向对象编程 第4章 Java 字符 […]

微信扫一扫

支付宝扫一扫

版权: 转载请注明出处:https://www.zuozi.net/9137.html

管理员

相关推荐
2025-08-06

文章目录 一、Reader 接口概述 1.1 什么是 Reader 接口? 1.2 Reader 与 InputStream 的区别 1.3 …

988
2025-08-06

文章目录 一、事件溯源 (一)核心概念 (二)Kafka与Golang的优势 (三)完整代码实现 二、命令…

465
2025-08-06

文章目录 一、证明GC期间执行native函数的线程仍在运行 二、native线程操作Java对象的影响及处理方…

348
2025-08-06

文章目录 一、事务基础概念 二、MyBatis事务管理机制 (一)JDBC原生事务管理(JdbcTransaction)…

456
2025-08-06

文章目录 一、SnowFlake算法核心原理 二、SnowFlake算法工作流程详解 三、SnowFlake算法的Java代码…

517
2025-08-06

文章目录 一、本地Jar包的加载操作 二、本地Class的加载方法 三、远程Jar包的加载方式 你知道Groo…

832
发表评论
暂无评论

还没有评论呢,快来抢沙发~

助力内容变现

将您的收入提升到一个新的水平

点击联系客服

在线时间:08:00-23:00

客服QQ

122325244

客服电话

400-888-8888

客服邮箱

122325244@qq.com

扫描二维码

关注微信客服号