第29篇:一篇文章详解Java 中的接口

简介: 📜 想象一下,未来社会,计算机在没有人操控的情况下控制智能汽车运送乘客穿越城市的大街小巷。汽车制造商用 Java 语言编写软件来控制汽车的启动、停止、加速和转弯等。另一个工业集团,电子导航仪器制造商制作计算机系统,用于接收 GPS(全球定位系统)位置数据和交通状况的无线传输,并使用这些信息来驾驶汽车。

一、接口介绍

(1) 生活中的 “接口”

在这里插入图片描述
在这里插入图片描述

📱 苹果手机的充电插口和安卓手机📲的充电插口是不一样的。例如:充电器有两个厂商生成(分别是:喜羊羊🐑厂商和老鼠厂商🐭),喜羊羊厂商和老鼠厂商各自制定了它们自己的充电器的大小和形状 标准(是方形还是圆形)。苹果🍎手机商家觉得老鼠厂商的(圆形)充电器比较好,所以苹果厂商按照老鼠厂商的充电器的 规范制作了苹果手机的充电插口。安卓手机的商家则觉得喜羊羊厂商的充电器比较酷,所以安卓手机的商家按照喜羊羊厂商的充电器 规范制作安卓手机的充电器插口。

☘️ 充电器的大小与形状就是一个规范,一个标准;手机若想使用该种类型的充电器充电,就必须按照该充电器的规范设计手机的充电插口。


在这里插入图片描述

🏘️ 在生活中, 接口二字应该最常使用在 USB 接口上。

Universal Serial Bus(通用串行总线)是一个外部总线标准,用于规范电脑与外部设备的连接和通讯;是应用在 PC 领域的接口技术。
🏘️ 电脑和外部设备的连接和通讯通过 USB 接口实现,USB 接口的大小和传输速率由 USB 厂商规定好(类似制定一个规范和标准),电脑若想通过 USB 连接外部设备,电脑就要按照 USB 厂商制定的 USB 的制作规范(标准) 来制作自己的 USB 插槽。【电脑生成商实现了 USB 接口的规范】


(2) 官方教程介绍

✏️ There are a number of situations in software engineering when it is important for disparate groups of programmers to agree to a contract(协议) that spells out(详细说明) how their software interacts. Each group should be able to write their code without any knowledge of how the other group's code is written. Generally speaking, interfaces are such contracts.
在这里插入图片描述

📜 在软件工程中,来自不同小组的程序设计者共同同意一份协议来详细阐明它们的软件如何进行交互是很重要的。
在这里插入图片描述

📜 每个组的程序设计者能够编写自己的代码,无需关心其他组的程序设计者的代码是如何编写的。一般来说:接口就是这样的一个协议(契约)


✏️ For example, imagine a futuristic(未来的) society where computer-controlled robotic cars transport(运送) passengers through city streets without a human operator.
✏️ Automobile manufacturers(汽车制造商) write software (Java, of course) that operates the automobile—stop, start, accelerate, turn left, and so forth.
✏️ Another industrial group, electronic guidance instrument manufacturers, make computer systems that receive GPS (Global Positioning System) position data and wireless transmission of traffic conditions and use that information to drive the car.
📜 想象一下,未来社会,计算机在没有人操控的情况下控制智能汽车运送乘客穿越城市的大街小巷。汽车制造商用 Java 语言编写软件来控制汽车的启动、停止、加速和转弯等。另一个工业集团,电子导航仪器制造商制作计算机系统,用于接收 GPS(全球定位系统)位置数据和交通状况的无线传输,并使用这些信息来驾驶汽车。
在这里插入图片描述


✏️ The auto manufacturers must publish an industry-standard interface that spells out in detail what methods can be invoked to make the car move (any car, from any manufacturer). The guidance manufacturers can then write software that invokes the methods described in the interface to command the car. Neither industrial group needs to know how the other group's software is implemented(实现). In fact, each group considers its software highly proprietary(专有性) and reserves the right to modify it at any time, as long as it continues to adhere to the published interface.
📜 汽车制造商必须发布一个行业标准接口,详细说明可以调用哪些方法来使汽车移动(任何汽车,来自任何制造商)。
📜 导航制造商可以编写软件来调用接口中的方法去控制汽车。
📜 两个工业集团都不需要知道其他集团的软件是如何实现的(如何实现使汽车启用)。事实上,每个团体都认为其软件具有高度专有性,并保留随时对其进行修改的权利,只要它继续遵守已发布的 协议(标准) 即可。
在这里插入图片描述


✏️ In the Java programming language, an interface is a reference type, similar to a class, that can contain only constants, method signatures, default methods, static methods, and nested types. Method bodies exist only for default methods and static methods. Interfaces cannot be instantiated—they can only be implemented by classes or extended by other interfaces.
📜 在 Java 语言中,接口和类一样是引用类型
📜 接口中只能包含:① 常量;② 方法签名;③ 默认方法;④ 静态方法;⑤ 嵌套类型
在这里插入图片描述
📜 在接口中,方法体只存在于默认方法和静态方法中
📜 接口不能被实例化
📜 接口只能被类实现(implements)或被其他接口继承


✏️ Note that the method signatures have no braces and are terminated with a semicolon.
📜 方法签名没有花括号,并由分号结尾

(3) 接口介绍

🌼 接口中定义一些抽象方法(没有具体实现),类可实现(implements)接口中的方法,给予接口中的抽象方法具体的实现
汽车接口:

/**
 * 汽车接口
 */
public interface ICar {
    int DEFAULT_SPEED = 30;

    Direction left = new Direction("左");
    Direction right = new Direction("右");

    void start();

    void stop();

    void accelerate(int speed);

    default void speak() {
        System.out.println("ICar_defaultMethod_speak()");
    }

    static void eat() {
        System.out.println("ICar_staticMethod_eat()");
    }

    class Direction {
        String name;

        Direction(String name) {
            this.name = name;
        }
    }
}

实现类:

/**
 * AutoControlCar 类实现(implements)ICar 接口
 * AutoControlCar 类给予 ICar 接口中的抽象方法具体实现
 */
public class AutoControlCar implements ICar {
    @Override
    public void start() {
        System.out.println("AutoControlCar - start()");
    }

    @Override
    public void stop() {
        System.out.println("AutoControlCar - stop()");
    }

    @Override
    public void accelerate(int speed) {
        System.out.println("AutoControlCar - accelerate()");
    }
}

🌼 jdk7 之前,接口中的全部方法都没有方法体
🌼 jdk8 之后,接口中可以有静态方法,默认方法(也就是接口中的方法可以有具体实现)

(4) 请家教

Interfaces are such contracts. 接口是一种协议
在这里插入图片描述

一个家长💁‍♀️ 要请家教👨‍🏫教 TA 的孩子学习,TA 对家教的要求如下:① 擅长英语;② 擅长数学;③ 擅长画画。

📖 接口是一种协议
📖 接口是一个标准
📖 接口是一个规范
要成为家教老师👨‍🏫只需满足协议中的内容即可
要成为家教老师👨‍🏫只需实现接口中的抽象方法即可
家长制定家教老师👩‍🏫的规范(接口),想要成为家教老师的人只需实现该规范(接口中的方法)即可

在这里插入图片描述

📖 接口是一种规范,某个类实现了该接口,则表明该类 能够做某事...
📖 上图:老师👨‍🏫实现了家教协议,表明老师可以当家教老师
机器人实现了家教协议,表明机器人可以当家教老师
狗🐶实现了家教协议,表明狗可以当家教老师

家教协议【接口】

/**
 * 家教协议, 家教接口
 */
public interface ITutor {
    void english();

    void math();

    void paint();
}

实现(implements)了 ITutor 接口的类有当家教的能力

/**
 * Teacher 实现了 ITutor
 * Teacher 有当家教的能力
 */
public class Teacher implements ITutor {
    @Override
    public void english() {
        System.out.println("Teachers teach English.");
    }

    @Override
    public void math() {
        System.out.println("Teachers teach math.");
    }

    @Override
    public void paint() {
        System.out.println("Teachers teach painting.");
    }
}
/**
 * Robot 实现了 ITutor
 * Robot 有当家教的能力
 */
public class Robot implements ITutor {
    @Override
    public void english() {
        System.out.println("Robots teach English.");
    }

    @Override
    public void math() {
        System.out.println("Robots teach math.");
    }

    @Override
    public void paint() {
        System.out.println("Robots teach painting.");
    }
}
/**
 * Dog 实现了 ITutor
 * Dog 有当家教的能力
 */
public class Dog implements ITutor {
    @Override
    public void english() {
        System.out.println("Dogs teach English.");
    }

    @Override
    public void math() {
        System.out.println("Dogs teach math.");
    }

    @Override
    public void paint() {
        System.out.println("Dogs teach painting.");
    }
}

接口是一种协议。接口的功能异常强大,博主有一点点开发经验,所以能够感受得到。

二、接口细节

✏️ 接口不能被实例化
✏️ 接口中的成员默认都是public(无需手动写 public
✏️ 接口中的方法默认都是抽象方法(无需手动写 abstract
✏️ 非抽象类实现(implements)接口,则必须实现接口中的所有抽象方法(给予接口中的所有抽象方法以具体实现
✏️ 抽象类实现接口,不用实现接口中的方法

public interface ITest {
    // interface 中的 test() 是一个抽象方法
    // 等价:public abstract void test();
    void test();
}
public abstract class AbstractTest implements ITest {
    /**
     * 下面的 public void test() {} 可认为是 ITest 接口中的 test
     * 方法的实现(但不是强制的)。当父接口中的抽象方法的方法签名和抽象类    
     * 中的成员
     * 方法的方法签名一样的时候, 返回值类型也要一样。
     */
    @Override
    public void test() {
        System.out.println("AbstractTest_test()");
    }
}
public class TestTest extends AbstractTest {
    public static void main(String[] args) {
        // AbstractTest_test()
        new TestTest().test();
    }
}    

✏️ 一个类可以同时实现多个接口

📒 该类需实现多个接口中的全部抽象方法,除非它是抽象类

✏️ 接口中的属性默认就是常量

public interface ITest {
    // 等价于:public static final int value = 888;
    int value = 888;
}
📒 访问接口中的属性:① 通过 接口名访问;② 通过该接口的实现类的类名访问;③ 通过该接口的实现类的实例对象访问

✏️ 一个接口可以继承(extends)多个接口(接口没有继承类的说法)
✏️ 接口只能被 public 关键字修饰,或没有访问修饰符


类实现接口,则有了接口中的常量

interface ITest {
    int value = 666;
}

class ITestImpl implements ITest {

}

public class DemoTest {
    public static void main(String[] args) {
        // 666
        System.out.println(ITest.value);
        // 666
        System.out.println(ITestImpl.value);

        // 666
        System.out.println(new ITestImpl().value); // 不推荐
    }
}

三、继承类和实现接口

✏️【继承类】Dog extends Animal: Dog is a kindof Animal.【狗是一种动物】
✏️【实现接口】GoodStudent implements Teachable: GoodStudent can do something.【好学生会某种能力(被定义在 Teachable 协议中的能力)】

接口和抽象类的选择

四、接口多态

(1) 多态参数

📖 学生购买手机,手机只需有两个功能即可(① 玩游戏;② 刷短视频)
📖 小米手机实现了( implements)InterPhone 接口,所以小米手机可能被购买
📖 华为手机实现了( implements)InterPhone 接口,所以华为手机可能被购买
📖 张思瑞同学购买了华为手机
📖 杨嘉立同学购买了小米手机
📖 两位同学都是 Student 类的实例对象
📖 写代码,实现上面描述的场景❓
public interface InterPhone {
    void playGame(String name);

    void seeVideo(String name);
}
public class XiaoMi implements InterPhone {
    @Override
    public void playGame(String name) {
        System.out.println(name + "_XiaoMi_playGame()");
    }

    @Override
    public void seeVideo(String name) {
        System.out.println(name + "_XiaoMi_seeVideo()");
    }
}
public class HuaWei implements InterPhone {
   @Override
   public void playGame(String name) {
       System.out.println(name + "_HuaWei_playGame()");
   }

   @Override
   public void seeVideo(String name) {
       System.out.println(name + "_HuaWei_seeVideo()");
   }
}
public class Student {
    private InterPhone phone;
    private String name;

    // 多态参数:InterPhone 可指向它的实现类的对象
    // 当传入不同的实现类对象的时候, phone 的指向是多种多样的
    public Student(String name, InterPhone phone) {
        this.name = name;
        this.phone = phone;
    }

    public String getName() {
        return name;
    }

    public InterPhone getPhone() {
        return phone;
    }
}
public class TestDemo {
    public static void main(String[] args) {
        Student zsr = new Student("张思瑞", new HuaWei());
        Student yjl = new Student("杨嘉立", new XiaoMi());

        // 张思瑞_HuaWei_playGame()
        zsr.getPhone().playGame(zsr.getName());
        // 杨嘉立_XiaoMi_seeVideo()
        yjl.getPhone().seeVideo(yjl.getName());
    }
}

(2) 多态数组

📖 数组定义的类型是接口数组类型
📖 数组中存放的是接口类型的实现类的类型

public interface InterPhone {
    void playGame(   );
}
public class XiaoMi implements InterPhone {
    @Override
    public void playGame() {
        System.out.println("小米手机打游戏");
    }

    public void cook() {
        System.out.println("小米手机可以炒菜");
    }
}
public class HuaWei implements InterPhone {
    public void playGame(   ) {
        System.out.println("华为手机玩游戏");
    }

    public void eat() {
        System.out.println("华为手机可以填饱肚子");
    }
}
public class Apple implements InterPhone {
    @Override
    public void playGame() {
        System.out.println("苹果手机耍游戏");
    }

    public void sleep() {
        System.out.println("苹果手机可以用来睡觉");
    }
}
public class TestDemo {
    public static void main(String[] args) {
        InterPhone[] phones = new InterPhone[3];
        phones[0] = new HuaWei();
        phones[1] = new XiaoMi();
        phones[2] = new Apple();
0
        for (InterPhone phone : phones) {
            phone.playGame();
            if (phone instanceof HuaWei) {
                HuaWei p = (HuaWei) phone;
                // 华为手机可以填饱肚子
                p.eat();
            }

            if (phone instanceof XiaoMi) {
                XiaoMi p = (XiaoMi) phone;
                // 小米手机可以炒菜
                p.cook();
            }

            if (phone instanceof Apple) {
                Apple p = (Apple) phone;
                // 苹果手机可以用来睡觉
                p.sleep();
            }
        }
        
        /*
            华为手机玩游戏
            华为手机可以填饱肚子
            小米手机打游戏
            小米手机可以炒菜
            苹果手机耍游戏
            苹果手机可以用来睡觉
         */
    }
}

(3) 接口多态传递

📖 ① InterB 接口继承了 InterA 接口;② InterBImpl 类实现 InterB 接口
📖 InterBImpl 类 需要实现 InterB 和 InterA 两个接口中的抽象方法
📖 InterB 和 InterA 两个接口都可以作为父接口引用类型指向 InterBImpl
在这里插入图片描述

public interface InterA {
    void a();
}
public interface InterB extends InterA {
    void b();
}
public class InterBImpl implements InterB {
    @Override
    public void b() {
        System.out.println("b");
    }

    @Override
    public void a() {
        System.out.println("a");
    }
}
public class TestDemo {
    public static void main(String[] args) {
        InterBImpl impl = new InterBImpl();
        InterA interA = impl;
        InterB interB = impl;

        // a
        interA.a();

        // b
        interB.b();
        // a
        interB.a();

        // a
        impl.a();
        // b
        impl.b();
    }
}

五、Exercise

实现的接口中的常量名和父类的属性名一样的时候会报错

interface Testable {
    int x = 0;
}

class Apple {
    int x = 1;
}

class Candy extends Apple implements Testable {
    public void printX() {
        // Reference to 'x' is ambiguous
        // both 'Apple.x' and 'Testable.x' match
        // ERROR
        // System.out.println(x);

        // 访问父类(Apple)的【x】
        System.out.println(super.x);

        // 访问父接口(Testable)的【x】
        System.out.println(Testable.x);
    }
}

public class TestDemo {
    public static void main(String[] args) {
        // 1
        // 0
        new Candy().printX();
    }
}

结束!如有错误,请不吝赐教

相关文章
|
19天前
|
Java
Java——抽象类和接口
抽象类是一种不能被实例化的类,至少包含一个抽象方法(无实现体的方法),常用于定义一组相关类的共同特征,并强制子类实现特定方法。抽象方法不能被 `static` 或 `final` 修饰,且必须被重写。 接口则是一个完全抽象的类,用于规范类的行为。接口使用 `interface` 关键字定义,不能实例化,并且类与接口之间是实现关系。 内部类是在一个类内定义的类,分为成员内部类、静态内部类、局部内部类和匿名内部类。成员内部类可被修饰符修饰,静态内部类只能访问外部类的静态成员,局部内部类定义在方法内,匿名内部类则隐藏了名字,直接通过 `new` 关键字定义并实现接口或继承类。
14 5
Java——抽象类和接口
|
19天前
|
Java
Java——接口的使用实例
Comparable接口用于自定义类的对象比较。通过实现此接口并重写`compareTo`方法,可以定义自定义类型的比较规则。 接下来介绍了Comparator接口,它提供了一种更灵活的比较方式。通过实现Comparator接口并重写`compare`方法,可以根据不同属性定义不同的比较规则。例如,定义一个`BrandComparator`类来比较汽车的品牌。 最后,介绍了Cloneable接口,用于实现对象的克隆。实现该接口并重写`clone`方法后,可以创建对象的浅拷贝或深拷贝。浅拷贝仅复制对象本身,深拷贝则会递归复制所有成员变量。
15 4
Java——接口的使用实例
|
4天前
|
Java 测试技术
Java接口的生产环境应用注意点
在Java生产环境中,合理使用接口对提升代码质量至关重要。设计接口时应遵循单一职责原则,采用清晰命名,并控制方法数量。默认方法应谨慎使用,避免与实现类产生冲突。通过版本化管理接口更新,确保向后兼容。实现接口时需明确行为,保持实现与接口分离,利用多态增强灵活性。关注性能影响,适当文档注释及充分测试确保接口稳定可靠。综合运用这些策略,可以显著提高系统的可扩展性和维护性。
|
4天前
|
Java
Java 接口的简化理解
Java 接口是一种强大的概念,用于定义方法签名而非具体实现,作为行为规范,强调功能而非实现细节。接口是特殊的引用类型,包含常量和方法签名。其特点包括:无实现方法体、支持多重继承、内置常量定义。通过示例展示了如何定义和实现接口,以及如何通过接口引用调用实现类的方法。接口的应用场景包括抽象化、插件架构和松耦合设计。从 Java 8 起,接口还支持默认方法和静态方法,进一步增强了其灵活性和扩展性。理解接口是 Java 编程的基础之一。
|
5天前
|
Java
接口和抽象类【Java面向对象知识回顾②】
本文讨论了Java中抽象类和接口的概念与区别。抽象类是不能被实例化的类,可以包含抽象和非抽象方法,常用作其他类的基类。接口是一种纯抽象类型,只包含抽象方法和常量,不能被实例化,且实现接口的类必须实现接口中定义的所有方法。文章还比较了抽象类和接口在实现方式、方法类型、成员变量、构造方法和访问修饰符等方面的不同,并探讨了它们的使用场景。
接口和抽象类【Java面向对象知识回顾②】
|
13天前
|
Java
领略Lock接口的风采,通过实战演练,让你迅速掌握这门高深武艺,成为Java多线程领域的武林盟主
领略Lock接口的风采,通过实战演练,让你迅速掌握这门高深武艺,成为Java多线程领域的武林盟主
22 7
|
9天前
|
JSON 前端开发 JavaScript
java中post请求调用下载文件接口浏览器未弹窗而是返回一堆json,为啥
客户端调接口需要返回另存为弹窗,下载文件,但是遇到的问题是接口调用成功且不报错,浏览器F12查看居然返回一堆json,而没有另存为弹窗; > 正确的效果应该是:接口调用成功且浏览器F12不返回任何json,而是弹窗另存为窗口,直接保存文件即可。
35 2
|
25天前
|
Java 数据库连接 数据库
Java服务提供接口(SPI)的设计与应用剖析
Java SPI提供了一种优雅的服务扩展和动态加载机制,使得Java应用程序可以轻松地扩展功能和替换组件。通过合理的设计与应用,SPI可以大大增强Java应用的灵活性和可扩展性。
48 18
|
22天前
|
Java 开发者
Java的接口详解
Java接口是编程中的一种重要特性,用于定义方法签名而不提供具体实现,作为类之间的契约,使不同类能以统一方式交互。接口使用`interface`关键字定义,可包含方法声明和常量。类通过`implements`关键字实现接口,并可同时实现多个接口,解决多重继承问题。接口中的方法默认为抽象方法,变量默认为`public static final`。Java 8引入了默认方法和静态方法,增强接口功能。接口广泛应用于回调机制和多态性实现,有助于构建更灵活和可维护的代码结构。
|
1月前
|
Java
盘点java8 stream中隐藏的函数式接口
`shigen`是一位坚持更新文章的博客作者,记录成长历程,分享认知见解,留住感动瞬间。本文介绍了函数式接口的概念及其在Java中的应用,包括`Comparator`、`Runnable`、`Callable`等常见接口,并详细讲解了`Function`、`Predicate`、`Consumer`、`Supplier`和`Comparator`等函数式接口的使用方法及应用场景,展示了如何利用这些接口简化代码并提高编程效率。**个人IP:shigen**,与shigen一起,每天进步一点点!
33 0
盘点java8 stream中隐藏的函数式接口
下一篇
无影云桌面