【Java课堂】接口详解

简介: 接口顾名思义,就是我们身边常用的行为规范。而接口在我们身边比比皆是,就比如电脑上的USB接口。USB接口插入U盘、鼠标、键盘....所有符合USB协议的设备,它把我们能用到的设备插头都统一起来,使得我们不用买大量的转换器,方便我们使用。

1、接口的概念

       接口顾名思义,就是我们身边常用的行为规范。而接口在我们身边比比皆是,就比如电脑上的USB接口。USB接口插入U盘、鼠标、键盘....所有符合USB协议的设备,它把我们能用到的设备插头都统一起来,使得我们不用买大量的转换器,方便我们使用。

总结来说:接口就是公共的行为规范,大家在实现时,只要符合规范标准,就可以通用。

在Java中,接口可以看成是:多个类的公共规范,是一种引用数据类型。

2、语法规则

接口的定义格式与定义类的格式基本相同,将class关键字换成interface即可定义接口

interface 接口名称{
    //成员变量  必须要初始化
    public static final int a = 10;
    int b = 10;
    //抽象方法
    public abstract void method1();
    void method2();
    //接口的默认方法
    default void func()1{
        ...
    }
    //接口静态成员方法
    static void func2(){
        ...
    }
}

实现接口有几条规范需要我们注意

接口当中的成员变量,默认都是 public static final 修饰的

接口当中的成员方法,默认都是抽象方法,public abstract 修饰的

接口当中的普通成员方法,是不能有具体的实现的

接口当中的普通成员方法,如果要有具体实现,必须加上default修饰【从JDK8开始,才有】

接口当中可以有静态的成员方法

接口中不管是静态的方法还是default方法,都是public修饰的

书写接口规范

创建接口时,接口的命名一般以大写字母 I 开头。

接口命名一般使用“形容词”词性的单词。

阿里编码规范中约定,接口中的方法和属性不要加任何修饰符号,保持代码的简洁性。

 3、接口的使用

        接口跟抽象类一样不能直接实例化,必须要有一个“实现类”来“实现”该接口,实现接口中的所有抽象方法。而类和接口的关系是使用 implements 来关联的

public class 类名称 implements 接口名称{
// ...
}

注意:子类和父类之间是extends 继承关系,类和接口之间是 implements 实现关系

        当类实现了接口,那么该类就必须实现接口中所有的抽象方法,否则编译器会报错


在IDEA中,有快捷键实现接口中的抽象方法。


首先把鼠标触碰implements,按下Alt+Shift+Enter 或点击 Implement methods 就会出现所有要实现抽象方法,点击OK即可完成

此外,接口也可以应用具体实现类。【向上转型】

interface  IShape{
    void draw();
}
class Rect implements IShape{
    @Override
    public void draw() {
        System.out.println("画一个正方形");
    }
}
class Flower implements IShape{
    @Override
    public void draw() {
        System.out.println("画一朵花");
    }
}
public class test {
    public static void drawMap(IShape iShape){
        iShape.draw();
    }
    public static void main(String[] args) {
        drawMap(new Rect());
        drawMap(new Flower());
        IShape iShape = new Flower();//向上转型
    }
}

7602a3853cf8f62283af8ec3f63ffcd4_9c47ce3c02f44571ac9cb132a442002d.png

4、接口的特性

1.接口类型是一种引用类型,但是不能直接new接口的对象

2.接口中的每一个方法都是 public 的抽象方法,即接口中普通侧成员方法会被隐式指定为 public abstract,且只能是 public abstract,其他修饰符都会报错。

197eab0c2c763d3e6f34cf3501d30883_aab92bdc378845af998ea7788c5e7253.png

3.接口中的方法一般不能在接口中实现,基本上都在实现接口的类来实现(在接口中default 修饰的方法可以具体实现)


4.重写接口方法时,所加访问权限必须要大于重写方法的访问权限


       如下,draw() 方法默认是public修饰。Rect类要重写draw方法,就必须要加public,否则会报错

36c01735717d60c57090bd52233b943d_020aacea161646f2b46fc48406eb472e.png

5.接口中可以含有变量,但是会被隐式指定为 public static final 变量

interface  IShape{
    double kind = 2.0;//默认被:public static final 修饰
    void draw();//默认public
}
public class test {
    public static void main(String[] args) {
        System.out.println(IShape.kind);//可以通过接口名访问
       //IShape.brand = 2.0;//无法为最终变量brand 分配值
    }
}

6.接口中不能有静态代码块和构造方法

473fd3509b6be79a9f0c17074910806a_e073a699bafe470a8b06ff8546f2bd5e.png

7.接口虽然不是类,但是接口编译完成后字节码文件的后缀格式也是.class

5、实现多个接口

在Java中,一个类只能继承一个父类,不支持多继承,而一个类却可以实现多个接口


       “假设有一条 鱼 和一只 鸟,让我们来写一串代码来实现它们的行为”。


  首先它们都是动物,我们都能给它们起名字,比如 “小花”、“小飞”....


  那我们能不能定义抽象类,来统一规范动物的特性和行为。如下

abstract class Animal{
    public String name;
    public Animal(String name) {
        this.name = name;
    }
}

       然后同时创建一个 鱼 类和一个鸟类,并继承Animal类

class Fish extends Animal{
    public Fish(String name) {
        super(name);
    }
}
class Bird extends Animal{
    public Bird(String name) {
        super(name);
    }
}

现在我们来思考一下,鱼和鸟都有什么行为?


鱼能吃饭、能游泳


鸟能吃饭、能飞


他们共同的共性是吃饭,不同的特性是游泳和飞


特性分析出来了,那我们该如何实现呢?


思考:我们能不能在 Animal 类中写 eating、swimming、flying这三个方法,并让子类继承并重写这些方法呢?


答:肯定是不行的,这样虽然能让Fish类和Bird类获各自的行为,但是鱼也获得了‘上天’【flying】的能力,鸟也获得了‘下海’【swimming】的能力,所以这样做法不行。


那假设我另创建一个游泳类,在类中实现游泳方法,并让Fish继承,大家想想这样可以吗?答案肯定也是不行的。

647de47b41da125e0b470441c1ac807e_67c98e86daa14c7d831d4d280bc52a5a.png

Java中只能单继承,所以这时我们要用接口来实现这一功能


既然我们不能把 鱼 和 鸟 的所有行为特性都写到父类当中,那么我们就把他们相同的特性行为写到父类中,然后再把他们特有的行为写到接口中。


所以我们可以直接定义三个接口,分别为ISwimming、IFlying、IEating。分比让Fish类和Bird类实现,下面以Fish类实现接口为例

1eb0e881bd2227cb60185c83adc7b59f_c4339bb193434d66b9bd636ec4423c65.png

此时我们可以定义三个方法来方便我们调用swmming、flying、eating等


这些方法分别用相应的接口接收参数,并在main函数中调用

2809da44b660e9826dec7618f29bc9a6_63f5b1e6bbdb4e2dbf1c8bc4e1ce34cf.png

结果如下

7d3d343ab92f386c97efc7e82ac2fc71_eae17f1456ab42789877b6a77609822c.png

此时如果 bird 能充当 swim 方法的参数吗?很明显不能。因为Bird类没有实现ISwimming接口。但是bird 和 fish 都能调用 eating 方法,这是因为 Fish 和 Bird 类都实现了IEating接口

5013d710c900a29c8597adabcfd22b4e_e078130328c64a69990c7f7890d4c863.png

interface ISwimming{
    void swimming();
}
interface IFlying{
    void flying();
}
interface IEating{
    void eating();
}
abstract class Animal{
    public String name;
    public Animal(String name) {
        this.name = name;
    }
}
class Fish extends Animal implements ISwimming,IEating{
    public Fish(String name) {
        super(name);
    }
    @Override
    public void swimming() {
        System.out.println(name+"正在游泳");
    }
    @Override
    public void eating() {
        System.out.println(name+"正在吃鱼食");
    }
}
class Bird extends Animal implements IFlying,IEating{
    public Bird(String name) {
        super(name);
    }
    @Override
    public void flying() {
        System.out.println(name+"正在飞");
    }
    @Override
    public void eating() {
        System.out.println(name+"正在此鸟粮");
    }
}
public class Test {
    public static void swim(ISwimming iSwimming){
        iSwimming.swimming();
    }
    public static  void fly(IFlying iFlying){
        iFlying.flying();
    }
    public static void eat(IEating iEating){
        iEating.eating();
    }
    public static void main(String[] args) {
        Fish fish = new Fish("小鱼");
        swim(fish);
        eat(fish);
        Bird bird = new Bird("小鸟");
        fly(bird);
        eat(bird);
    }
}

上面代码展示了Java 面向对象编程中最常见的用法:一个类继承一个父类,同时实现多个接口。


继承表达的含义时 is-a 含义,而接口表达的含义时 具有xxxx特性


鱼是一种动物,能吃,能游泳

鸟也是一种动物,能吃,能飞

这样设计什么好处呢?可以我们 👨‍💻程序员👩‍💻 时时刻刻记着多态的好处,忘记类型。有了接口之后,类的使用中就不必关注具体类型,而只关注某个类是否具有某种能力。

6、接口间的继承

在Java中,类和类之间是单继承的,一个类可以实现多个接口,接口与接口之间可以多继承。即:用接口可以达到多继承的目的。


接口可以继承一个接口, 达到复用的效果. 使用 extends 关键字.

interface IRunning {
    void run();
} 
interface ISwimming {
    void swim();
}
// 两栖的动物, 既能跑, 也能游
interface IAmphibious extends IRunning, ISwimming {
}
class Frog implements IAmphibious {
    ...
}

通过接口继承创建一个新的接口 IAmphibious 表示 "两栖的". 此时实现接口创建的 Frog 类, 就继续要实现 run 方法, 也需要实现 swim 方法。


接口间的继承相等于把多个接口合并在一起。


相关文章
|
4天前
|
JSON Java Apache
非常实用的Http应用框架,杜绝Java Http 接口对接繁琐编程
UniHttp 是一个声明式的 HTTP 接口对接框架,帮助开发者快速对接第三方 HTTP 接口。通过 @HttpApi 注解定义接口,使用 @GetHttpInterface 和 @PostHttpInterface 等注解配置请求方法和参数。支持自定义代理逻辑、全局请求参数、错误处理和连接池配置,提高代码的内聚性和可读性。
|
25天前
|
算法 Java 数据处理
从HashSet到TreeSet,Java集合框架中的Set接口及其实现类以其“不重复性”要求,彻底改变了处理唯一性数据的方式。
从HashSet到TreeSet,Java集合框架中的Set接口及其实现类以其“不重复性”要求,彻底改变了处理唯一性数据的方式。HashSet基于哈希表实现,提供高效的元素操作;TreeSet则通过红黑树实现元素的自然排序,适合需要有序访问的场景。本文通过示例代码详细介绍了两者的特性和应用场景。
36 6
|
25天前
|
存储 Java 数据处理
Java Set接口凭借其独特的“不重复”特性,在集合框架中占据重要地位
【10月更文挑战第16天】Java Set接口凭借其独特的“不重复”特性,在集合框架中占据重要地位。本文通过快速去重和高效查找两个案例,展示了Set如何简化数据处理流程,提升代码效率。使用HashSet可轻松实现数据去重,而contains方法则提供了快速查找的功能,彰显了Set在处理大量数据时的优势。
31 2
|
5天前
|
Java
java线程接口
Thread的构造方法创建对象的时候传入了Runnable接口的对象 ,Runnable接口对象重写run方法相当于指定线程任务,创建线程的时候绑定了该线程对象要干的任务。 Runnable的对象称之为:线程任务对象 不是线程对象 必须要交给Thread线程对象。 通过Thread的构造方法, 就可以把任务对象Runnable,绑定到Thread对象中, 将来执行start方法,就会自动执行Runable实现类对象中的run里面的内容。
18 1
|
11天前
|
Java 开发者
在Java多线程编程的世界里,Lock接口正逐渐成为高手们的首选,取代了传统的synchronized关键字
在Java多线程编程的世界里,Lock接口正逐渐成为高手们的首选,取代了传统的synchronized关键字
38 4
|
17天前
|
安全 Java
在 Java 中使用实现 Runnable 接口的方式创建线程
【10月更文挑战第22天】通过以上内容的介绍,相信你已经对在 Java 中如何使用实现 Runnable 接口的方式创建线程有了更深入的了解。在实际应用中,需要根据具体的需求和场景,合理选择线程创建方式,并注意线程安全、同步、通信等相关问题,以确保程序的正确性和稳定性。
|
15天前
|
Java
Java基础(13)抽象类、接口
本文介绍了Java面向对象编程中的抽象类和接口两个核心概念。抽象类不能被实例化,通常用于定义子类的通用方法和属性;接口则是完全抽象的类,允许声明一组方法但不实现它们。文章通过代码示例详细解析了抽象类和接口的定义及实现,并讨论了它们的区别和使用场景。
|
16天前
|
Java 测试技术 API
Java零基础-接口详解
【10月更文挑战第19天】Java零基础教学篇,手把手实践教学!
16 1
|
21天前
|
Java 开发者
在Java多线程编程中,创建线程的方法有两种:继承Thread类和实现Runnable接口
【10月更文挑战第20天】在Java多线程编程中,创建线程的方法有两种:继承Thread类和实现Runnable接口。本文揭示了这两种方式的微妙差异和潜在陷阱,帮助你更好地理解和选择适合项目需求的线程创建方式。
15 3
|
21天前
|
Java
在Java多线程编程中,实现Runnable接口通常优于继承Thread类
【10月更文挑战第20天】在Java多线程编程中,实现Runnable接口通常优于继承Thread类。原因包括:1) Java只支持单继承,实现接口不受此限制;2) Runnable接口便于代码复用和线程池管理;3) 分离任务与线程,提高灵活性。因此,实现Runnable接口是更佳选择。
29 2