java基础知识之接口---超详细(保姆级)

今天我们聊聊java基础知识中的接口,接口这个名字听起来有些抽象,没错接口其实就是抽象的,大家这时候就有疑问了,抽象类不能用么,为什么又出现一个接口的概念,让人真的觉得繁杂,前几篇我给大家说过,任何一项新技术的产生都是为了方便简单的实现某种目的。

那么说这么多还是没明白接口是干啥的呀,接口其实将实现功能范围扩大了,比如马儿会跑,汽车也会跑,跑这个动作是不同种类之间实现的,比如马儿是动物大类中的,汽车是机械大类中的,汽车和马儿都不在同种大类范围下,那么抽象类范围小点相当于同种类中不同对象对方法的不同实现,比如动物类下小猫小狗都实现跑这个动作。

抽象类类比:

接口类比:

从上边两个图片可以看出,其实接口的出现就是将类的实现范围扩大了,那么大家思考个问题,接口能像普通类一样实现接口之间的继承吗?答案是可以的,但是接口不是类,类只能实现单继承,而接口可以实现多继承。

接口间的继承

假设我们有一家公司,公司有DevOps (运维)、Tester (测试)、Developer (开发)和ProductManager (产品经理)。

然后,我们让ProductManager (产品经理)接口继承DevOpsTesterDeveloper三个接口,形成多继承。

DevOps(运维)接口:

csharp 复制代码
public interface DevOps {

    void deployApp(); // 部署应用
    default void handleIncidents() { // 处理事故
        System.out.println("运维人员处理事故...");
    }
}

Tester(测试)接口:

csharp 复制代码
public interface Tester {
    void exeTests(); // 执行测试
    default void reportBugs() { // 报告缺陷
        System.out.println("测试人员报告系统缺陷...");
    }

}

Developer(开发)接口:

csharp 复制代码
public interface Developer {

    void writeCode(); // 编写代码
    default void refCode() { // 重构代码
        System.out.println("开发人员重构代码...");
    }

}

ProductManager(产品经理)接口:

csharp 复制代码
public interface ProductManager extends DevOps, Tester, Developer{
    void gatherRequirements(); // 收集需求
    // 默认方法 - 协调不同团队
    default void coordTeams() {
        System.out.println("产品经理协调开发、运维、测试...");
    }

}

我们会发现ProductManager (产品经理)接口继承了三个父接口,DevOps (运维)、Tester (测试)、Developer (开发),说明产品经理三个父接口的6个方法还有自己的一个抽象方法和一个默认方法,那么产品经理就有8个方法,这个时候还不能直接的使用接口中的方法,需要有实现类来实现产品经理这个接口,通过实现类创建相关类对象并对接口的抽象方法进行重写,这时候接口中的默认方法和重写的方法就可以被调用了,其实接口中定义的方法就像一颗子弹,没有枪是无法发挥其本身的威力的,那么接口的实现类就是子弹的发射器,就是枪。

接口的实现

我们让TechManager (技术总监)去实现ProductManager(产品经理)的这个接口。

typescript 复制代码
public class TechManager implements ProductManager{
    private String name;

    public TechManager(String name) {
        this.name = name;
    }

    // 实现ProductManager接口的方法
    @Override
    public void gatherRequirements() {
        System.out.println(name + " 产品经理收集需求抽象方法重写.");
    }

    // 实现DevOps接口的方法
    @Override
    public void deployApp() {
        System.out.println(name + " 运维部署应用抽象方法重写.");
    }

    // 实现Tester接口的方法
    @Override
    public void exeTests() {
        System.out.println(name + " 测试抽象方法重写.");
    }

    // 实现Developer接口的方法
    @Override
    public void writeCode() {
        System.out.println(name + " 开发写代码抽象方法重写.");
    }

    // 重写默认方法以提供特定实现
    @Override
    public void coordTeams() {
        System.out.println(name + " 技术总监重写产品经理协调团队默认方法 .");
    }
}

测试代码:

csharp 复制代码
public class StartDemo {
    public static void main(String[] args) {
        // 创建技术总监实例
       TechManager pm = new TechManager("Tom");

        System.out.println("=== 产品经理职责 ===");
        pm.gatherRequirements();
        pm.coordTeams();
        System.out.println("=== 运维技能 ===");
        pm.deployApp();
        pm.handleIncidents(); // 使用继承的默认方法
        System.out.println("=== 测试技能 ===");
        pm.exeTests();
        pm.reportBugs(); // 使用继承的默认方法

        System.out.println("=== 开发技能 ===");
        pm.writeCode();
        pm.refCode(); // 使用继承的默认方法
    }

}

测试代码运行效果:

我们看到实现类实现了产品经理的接口,而产品经理接口继承了3个接口的所有方法,则TechManager (技术总监)这个类要重写DevOps (运维)、Tester (测试)、Developer (开发)ProductManager (产品经理)的所有抽象方法,那么接口中有了抽象方法还要默认方法干啥?接口中默认方法是为了如果有多个实现类中有相同的行为,那么避免重复在实现类中写出冗余方法,这个就是类去实现接口的意义,如果这个类不想重写接口中的抽象方法的话,这个类也只能以抽象类的形式存在,看到这的朋友们是不是在接口中没有看到属性?其实接口中的属性可以理解为不可更改常量,这个通常以 " public static final int x = 1"的形式存在,这样定义避免了多继承中属性的不确定性,这个接口常量相当于全局统一。

接口与抽象类

在实际应用中我们应该如何在接口和抽象类中进行选型:

其实大部分实际的应用中都是接口和抽象类组合使用,这样可以提高代码的灵活性和复用性,组合使用使得代码既有统一契约又有共享实现的特点,接下来我们看看接口和抽象类组合的例子,加深一下对接口和抽象类组合的理解深度。

我们有一个接口Switchable ,一个实现接口的抽象类AbstractSwitch ,一个具体类Light 继承抽象类去实现具体的行为。

Switchable接口:

csharp 复制代码
public interface Switchable {
    void turnOn();
    void turnOff();
    boolean status();
}

AbstractSwitch抽象类:

typescript 复制代码
public abstract class AbstractSwitch implements Switchable{
    protected boolean status = false;

    @Override
    public void turnOn() {
        status = true;
        System.out.println("设备开启...");
    }

    @Override
    public void turnOff() {
        status = false;
        System.out.println("设备关闭...");
    }

    @Override
    public boolean status() {
        return status;
    }

    // 抽象方法 - 由子类实现具体行为
    protected abstract void deviceAction();
}

Light具体类:

typescript 复制代码
public class Light extends AbstractSwitch {
    @Override
    protected void deviceAction() {
        if (status()) {
            System.out.println("设备灯亮...");
        } else {
            System.out.println("设备灯关闭...");
        }
    }

    @Override
    public void turnOn() {
        super.turnOn();
        deviceAction();
    }
    @Override
    public void turnOff() {
        super.turnOff();
        deviceAction();
    }
}

测试代码:

typescript 复制代码
public class StartDemo1 {
    public static void main(String[] args) {
        Switchable light = new Light();
        light.turnOn();
        light.turnOff();
    }

}

运行测试代码的效果:

从上面我们可以看出接口Switchable 定义了设备应该具备的基本操作(契约),抽象类AbstractSwitch 实现了接口Switchable 并对接口Switchable 中的抽象方法进行了重写,AbstractSwitch 提供了开关状态的通用实现,但留下了 deviceAction() 方法待具体实现,具体类对deviceAction() 进行了重写实现具体功能。

好了,接口部分的知识就给大家分享的到这里了,谢谢大家的观看与支持,下期我们再见。

相关推荐
UrbanJazzerati4 小时前
一文带你了解表语
面试
聪明的笨猪猪6 小时前
Java “并发工具类”面试清单(含超通俗生活案例与深度理解)
java·经验分享·笔记·面试
GISer_Jing11 小时前
明天好好总结汇总分析博客
前端·javascript·面试
sophie旭1 天前
一道面试题,开始性能优化之旅(8)-- 构建工具和性能
前端·面试·性能优化
Focusbe1 天前
百变AI助手:离线优先数据同步方案设计
前端·后端·面试
nice_lcj5201 天前
深入理解ArrayList与LinkedList:Java集合框架核心对比(含实战案例+面试考点)
java·面试
nju_spy1 天前
大模型面经(一) Prompt + RAG + 微调
人工智能·面试·lora·大模型·rag·提示词工程·peft微调
聪明的笨猪猪1 天前
Java 内存模型(JMM)面试清单(含超通俗生活案例与深度理解)
java·经验分享·笔记·面试
9号达人1 天前
Java20 新特性详解与实践
java·后端·面试