zl程序教程

您现在的位置是:首页 >  后端

当前栏目

【 java 面向对象】接口

JAVA接口 面向对象
2023-09-27 14:26:52 时间

请添加图片描述

前言

这一节我写一点java面向对象中比较重要的一部分:接口,也意味着面向对象系列即将完工!

接口概述

  • 一方面,有时必须几个类中派生出一个子类,继承它们所有的属性和方
    法。但是, Java 不支持多重继承,有了接口,就可以得到多重继承的效果。
  • 另一方面,有时必须从几个类中抽取出一些共同的行为特征,而它们之间又没有关系,仅仅是具有相同的行为特征而己。例如:鼠标、键盘、打印机、扫描仪、摄像头、充电器、MP3机、手机、数码相机、移动硬盘等都支持 USB 连接。
  • 接口就是规范,定义的是一组规则,体现了现实世界中“如果你是要...则必须能..”的思想。继承是一个"是不是"的关系,而接口实现则是"能不能”的关系。
  • 接口的本质是契约,标准,规范,就像我们的法律一样。制定好后大家都要遵守。

定义接口

1.接口使用 interface 来定义
2.Java中,接口和类是并列的两个结构

JDK7

JDK7及以前:只能定义全局常量和抽象方法
全局常量: public static final 的。但是书写时,可以省略不写。
抽象方法: public abstract 的,书写时可省略。

interface A{
    public static final int x = 1;
    int y = 2;  //省略public static final
    public abstract void method1();
    void method2();  //省略public abstract
}

JDK8

JDK8,除了定义全局常量和抽象方法之外,还可以定义静态方法、默认方法
从技术角度来说,这是完全合法的,只是它看起来违反了接口作为一个抽象定义的理念。

  • 静态方法:使用 static 关键字修饰。可以通过接口直接调用静态方法,并执行其方法体。我们经常在相互一起使用的类中使用静态方法。你可以在标准库中找到像 Collection / Collections 或者 Path / Paths 这样成对的接口和类。

  • 默认方法:默认方法使用 default 关键字修饰。可以通过实现类对象来调用。我们在已有的接口中提供新方法的同时,还保持了与旧版本代码的兼容性。比如: java 8API中对 Colection 、 List 、 comparator 等接口提供了丰富的默认方法。默认方法也可以被重写。

interface A{
    //JDK7
    public static final int x = 1;
    int y = 2;  //省略public static final
    public abstract void method1();
    void method2();  //省略public abstract

    //JDK8
    public static void method3() {
        System.out.println("接口中的静态方法!");
    }
    
    public default void method4(){
        System.out.println("接口中的默认方法!");
    }
}

接口的实现

接口中不能定义构造器的!意味着接口不可以实例化
Java开发中,接口通过让类去实现==( implements )==的方式来使用。

  • 如果实现类盖了接口中的所有抽象方法,则此实现类就可以实例化。
  • 如果实现类没有覆盖接口中所有的抽象方法,则此实现类仍为一个抽象类。
interface A{
    //JDK7
    public static final int x = 1;
    int y = 2;  //省略public static final
    public abstract void method1();
    void method2();  //省略public abstract

    //JDK8
    public static void method3() {
        System.out.println("接口中的静态方法!");
    }

    public default void method4(){
        System.out.println("接口中的默认方法!");
    }
}

class B implements A{
    @Override
    public void method1() {
        System.out.println("重写的抽象方法1");
    }

    @Override
    public void method2() {
        System.out.println("重写的抽象方法2");
    }

    @Override
    public void method4() {
        // 接口中默认方法的调用
        A.super.method4();
        System.out.println("重写的默认方法");
    }
}

创建接口的匿名实现类

前面我们在讲抽象类时写过怎样创建抽象类的匿名子类,这里同样的,我们也可以创建接口的匿名实现类。

// 创建接口的匿名实现类  ---A是接口
A a = new A(){
    @Override
    public void method1() {
        System.out.println("接口的匿名实现类重写的抽象方法一"); 
    }

    @Override
    public void method2() {
        System.out.println("接口的匿名实现类重写的抽象方法二");
    }
    
    // 接口的匿名实现类重写的默认方法
    @Override
    public void method4() {
        A.super.method4(); //在接口的实现类中调用接口未重写的默认方法
        System.out.println("接口的匿名实现类重写的默认方法");
    }
};

完整Demo

package 接口;

public class Demo {
    public static void main(String[] args) {
        B b = new B();
        // 接口中抽象方法的调用
        System.out.println("------接口中抽象方法的调用------");
        b.method1();
        b.method2();

        // 接口中静态方法的调用
        System.out.println("------接口中静态方法的调用------");
        A.method3();

        // 接口中默认方法的调用(若重写了默认方法,则调用重写的)
        System.out.println("------接口中默认方法的调用------");
        b.method4();

        // 接口中全局常量调用
        System.out.println("------接口中全局常量调用------");
        System.out.println(A.x + " " + A.y);

        // 创建接口的匿名实现类
        System.out.println("------接口的匿名实现类------");
        A a = new A(){
            @Override
            public void method1() {
                System.out.println("接口的匿名实现类重写的抽象方法一");
            }

            @Override
            public void method2() {
                System.out.println("接口的匿名实现类重写的抽象方法二");
            }

            // 接口的匿名实现类重写的默认方法
            @Override
            public void method4() {
                A.super.method4(); //在接口的实现类中调用接口未重写的默认方法 // 注意是接口名.super
                System.out.println("接口的匿名实现类重写的默认方法");
            }
        };

        // 匿名实现类种方法的调用
        a.method1();
        a.method2();
        a.method4();



    }

}

interface A{
    //JDK7
    public static final int x = 1;
    int y = 2;  //省略public static final
    public abstract void method1();
    void method2();  //省略public abstract

    //JDK8
    public static void method3() {
        System.out.println("接口中的静态方法!");
    }

    public default void method4(){
        System.out.println("接口中的默认方法!");
    }
}

class B implements A{
    @Override
    public void method1() {
        System.out.println("重写的抽象方法1");
    }

    @Override
    public void method2() {
        System.out.println("重写的抽象方法2");
    }

    @Override
    public void method4() {
        // 接口的实现类中的未重写的接口默认方法的调用
        A.super.method4(); // 注意是接口名.super
        System.out.println("重写的默认方法");
    }
}

在这里插入图片描述

其他补充

  • java类可以实现多个接口—>弥补了 Java 单继承性的局限性
    格式: class AA extends BB implements CC , DD , EE

  • 接口与接口之间可以继承,而且可以多继承。

  • 接口的具体使用,体现多态性。

  • 接口,实际上可以看做是一种规范。

  • 如果子类(或实现类)继承的父类和实现的接口中声明了同名同参数的默认方法,那么子类在没有重写此方法的情况下,默认调用的是父类中的同名同参数的方法。->类优先原则

  • 如果实现类实现了多个接口,而这多个接口中定义了同名同参数的默认方法,那么在实现类没有重写此方法的情况下,报错。–>接口冲突。这就需要我们必须在实现类中重写此方法。

  • 如果一个类既有父类,又实现了接口,在父类和接口中各有一个同名的变量。那么子类输出这个变量是时也会报错,此时输出的这个变量是不明确的!

结语

如果你觉得博主写的还不错的话,可以关注一下当前专栏,博主会更完这个系列的哦!也欢迎订阅博主的其他好的专栏。

🏰系列专栏
👉软磨 css
👉硬泡 javascript
👉flask框架快速入门