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

【Java】接口interface学习

参考资料::黑马程序员·入门到飞起上

1 概述

在学习完抽象类后,我们了解到抽象类中既可以包含抽象方法,也能有普通方法、构造方法以及成员变量等。而接口则是一种更为彻底的抽象形式。在JDK7及之前的版本中,接口内全部为抽象方法,并且接口同样无法创建对象。

在Java中,接口(Interface)在JDK 7之前和之后(主要是JDK 8及更高版本)有显著的区别,主要体现在功能扩展上。以下是主要差异:

2 JDK7和它之后版本的区别

特性JDK 7及之前JDK 8及之后
抽象方法仅支持支持
默认方法不支持支持(default
静态方法不支持支持
私有方法不支持JDK 9+支持
常量字段支持支持
函数式接口无明确支持支持(@FunctionalInterface

3 接口成分的特点

在JDK7及之前,接口主要包含抽象方法和常量。

3.1抽象方法

需要注意的是,接口中的抽象方法默认会自动添加public abstract修饰,程序员无需手动书写。按照规范,日后在接口中定义抽象方法时,建议省略public abstract,因为系统会自动添加。

3.2 常量

在接口中定义的成员变量,默认会被public static final修饰。这意味着接口中定义的成员变量实际上是常量。经public static final修饰后,变量值不可修改,且由于其静态化特性,可直接通过接口名访问,因此称为常量。常量命名规范建议全部字母大写,多个单词间用下划线连接。

3.3 案例演示

以下通过具体代码示例展示接口的定义:

public interface InterF {// 抽象方法!//    public abstract void run();void run();//    public abstract String getName();String getName();//    public abstract int add(int a, int b);int add(int a, int b);// 它的最终写法是:// public static final int AGE = 12 ;int AGE = 12; //常量String SCHOOL_NAME = "黑马程序员";
}

4 基本的实现

4.1 实现接口的概述

在Java中,类与接口之间存在实现关系,即类实现接口。实现接口的类被称为接口的实现类,也可称作接口的子类。实现的操作类似于继承,格式相似,只是使用的关键字不同,实现使用implements关键字。

4.2 实现接口的格式

接口实现的格式如下:

/**接口的实现:在Java中接口是被实现的,实现接口的类称为实现类。实现类的格式:*/
class 类名 implements 接口1,接口2,接口3...{}

从上述格式可以看出,一个类可以实现多个接口,即接口支持多实现。这是因为接口代表一种规范,一个类可以遵循多种不同的规范,以满足不同方面的功能需求。

4.3 类实现接口的要求和意义

  1. 实现类必须重写其所实现的全部接口中的所有抽象方法。
  2. 如果一个类实现了接口,但未重写全部接口的所有抽象方法,那么这个类必须被定义为抽象类。
  3. 意义:接口体现的是一种规范,它对实现类具有强制性的约束。实现类要么完整实现接口所声明的功能,要么自身定义为抽象类。这种强制性规范确保了程序的一致性和规范性,不同的实现类按照统一的接口规范实现特定功能,便于代码的组织和维护。

情况 1:普通类不实现全部方法(❌ 编译错误)

interface Animal {void eat();void sleep();
}class Dog implements Animal {  // ❌ 编译错误:必须实现所有接口方法@Overridepublic void eat() {System.out.println("Dog is eating.");}// 缺少 sleep() 的实现
}

错误信息:

Error: Dog is not abstract and does not override abstract method sleep() in Animal

情况 2:抽象类不实现全部方法(✔️ 合法)
如果类声明为 abstract,则可以 不实现接口的部分或全部方法,但子类仍需实现剩余方法。

interface Animal {void eat();void sleep();
}abstract class AbstractDog implements Animal {  // ✔️ 合法:抽象类可以不实现接口方法@Overridepublic void eat() {System.out.println("AbstractDog is eating.");}// 未实现 sleep(),由子类完成
}class RealDog extends AbstractDog {  // 子类必须实现剩余的 sleep()@Overridepublic void sleep() {System.out.println("RealDog is sleeping.");}
}

情况 3:接口有默认方法(Java 8+ ✔️ 合法)
如果接口方法有 default 实现,实现类可以 选择不重写

interface Animal {void eat();default void sleep() {  // 提供默认实现System.out.println("Animal is sleeping.");}
}class Dog implements Animal {  // ✔️ 合法:只需实现 eat()@Overridepublic void eat() {System.out.println("Dog is eating.");}// 不重写 sleep(),直接使用接口的默认实现
}

调用:

Dog dog = new Dog();
dog.eat();   // 输出: Dog is eating.
dog.sleep(); // 输出: Animal is sleeping. (使用默认方法)

场景是否合法说明
普通类不实现全部方法编译错误,必须实现所有抽象方法
抽象类不实现全部方法✔️剩余方法由子类实现
接口有 default 方法✔️可选择性重写

4.4 类与接口基本实现案例

以定义一个运动员的接口(规范)为例,代码如下:

/**接口:接口体现的是规范。* */
public interface SportMan {void run(); // 抽象方法,跑步。void law(); // 抽象方法,遵守法律。String compittion(String project);  // 抽象方法,比赛。
}

接下来定义一个乒乓球运动员类作为接口的实现类,代码如下:

package com.itheima;
/*** 接口的实现:*    在Java中接口是被实现的,实现接口的类称为实现类。*    实现类的格式:*      class 类名 implements 接口1,接口2,接口3...{***      }* */
public class PingPongMan implements SportMan {@Overridepublic void run() {System.out.println("乒乓球运动员稍微跑一下!!");}@Overridepublic void law() {System.out.println("乒乓球运动员守法!");}@Overridepublic String compittion(String project) {return "参加" + project + "得金牌!";}
}

以下是测试代码:

public class TestMain {public static void main(String[] args) {// 创建实现类对象。PingPongMan zjk = new PingPongMan();zjk.run();zjk.law();System.out.println(zjk.compittion("全球乒乓球比赛"));}
}

4.5 类与接口的多实现案例

类与接口之间支持多实现关系,即一个类可以同时实现多个接口。
首先定义两个接口,代码如下:

/** 法律规范:接口*/
public interface Law {void rule();
}/** 这一个运动员的规范:接口*/
public interface SportMan {void run();
}

然后定义一个实现类:

/*** Java中接口是可以被多实现的:*    一个类可以实现多个接口: Law, SportMan** */
public class JumpMan implements Law, SportMan {@Overridepublic void rule() {System.out.println("尊长守法");}@Overridepublic void run() {System.out.println("训练跑步!");}
}

从上述代码可以看出,类与接口之间的多实现关系使得一个类能够遵循多种不同的规范,这在实际编程中具有重要意义,它允许类在不同的功能维度上进行扩展和实现。

5 接口与接口的多继承

在Java中,接口与接口之间支持多继承关系,即一个接口可以同时继承多个接口。需要明确的是,类与接口是实现关系,而接口与接口是继承关系。接口继承接口的本质是将其他接口的抽象方法与本接口进行合并。
以下是案例演示:

public interface Abc {void go();void test();
}/** 法律规范:接口*/
public interface Law {void rule();void test();
}**  总结:*     接口与类之间是多实现的。*     接口与接口之间是多继承的。* */
public interface SportMan extends Law, Abc {void run();
}

6 扩展:接口的细节

在接口的使用过程中,有一些语法细节需要注意。这些细节无需刻意背诵,当在开发工具(如IDEA)中出现报错时,能够知道如何修改即可。理解这些细节的关键在于把握抽象的本质。

  1. 当两个接口中存在相同抽象方法的时候
    只需要在实现类中重写一次该方法。此时这个重写的方法,既满足了第一个接口的抽象方法重写要求,也满足了第二个接口的要求。

  2. 实现类能否在继承A类的同时实现其他接口
    可以。继承的父类可类比为“亲爸爸”,实现的接口可类比为“干爹”。实现类能够在继承一个类的同时,实现多个接口,但需要将接口中的所有抽象方法全部实现。

  3. 实现类能否在继承一个抽象类的同时实现其他接口
    同样可以。实现类在继承一个抽象类的同时,实现其他多个接口时,需将抽象类和接口中的所有抽象方法全部重写。

  4. 实现类Zi实现了一个接口,还继承了一个Fu类,且接口与父类中有相同方法时

    • 处理办法一:若父类中的方法体能够满足当前业务需求,子类中可不重写该方法。
    • 处理办法二:若父类中的方法体无法满足当前业务需求,则需要在子类中重写该方法。
  5. 如果一个接口中有10个抽象方法,但在实现类中只需要使用其中一个
    可以在接口与实现类之间新建一个中间类(也称为适配器类)。让这个适配器类实现接口,并对接口中的所有方法进行空重写。然后让子类继承这个适配器类,根据实际需求重写需要使用的方法。由于中间类通常不具备实际业务意义,一般将其定义为抽象类,以防止外界创建对象。这种方式在实际开发中能够有效减少实现类的代码冗余,提高代码的灵活性和可维护性。

相关文章:

  • 残烛与风儿的对话
  • OC底层原理【一】 alloc init new
  • java单元测试不能点击run运行测试方法
  • 【第二天】一月速通Python第二天,函数,数据容器,列表,元组,字典。
  • 论文阅读:2023 arxiv A Survey of Reinforcement Learning from Human Feedback
  • 集成运放的关键技术参数
  • 7.0/Q1,Charls最新文章解读
  • 【Oracle专栏】Oracle中的虚拟列
  • pnpm确认全局下载安装了还是显示cnpm不是内部或外部命令,也不是可运行的程序
  • 算法分析传输加密数据格式密文存储代码混淆逆向保护
  • Mac上Cursor无法安装插件解决方法
  • 【大模型】RAG(Retrieval-Augmented Generation)检索增强生成
  • 使用 NEAT 进化智能体解决 Gymnasium 强化学习环境
  • 分布类相关的可视化图像
  • 从内核到用户态:Linux信号内核结构、保存与处理全链路剖析
  • DMA映射
  • 大模型S2S应用趋势感知分析
  • SSM(SpringMVC+spring+mybatis)整合的步骤以及相关依赖
  • 计算机视觉与深度学习 | LSTM原理,公式,代码,应用
  • n8n 中文系列教程_04.半开放节点深度解析:Code与HTTP Request高阶用法指南
  • 华天酒店:2024年归母净亏损约1.81亿元,已连续亏损3年
  • 上海银行换帅:顾建忠出任党委书记,金煜辞任董事长
  • 《哪吒2》票房已达157亿,光线传媒一季度净利增至20亿元
  • 上海开展数据产品知识产权登记存证试点,243个产品许可收益超20亿元
  • 执政将满百日,特朗普政府面临国内“三重暴击”
  • 最高法:抢票软件为用户提供不正当优势,构成不正当竞争