• Java接口的相关知识


    接口的概念

    在生活中,接口的例子比比皆是,比如,电脑上的USB接口、电源插座、手机type-c接口
    在这里插入图片描述
    电脑上USB接口,可以插:U盘、鼠标、键盘…所有符合USB协议的设备;
    电源插座的插口上,可以插:电脑、电视、吹风机…所有符合规范的电器;
    通过以上的例子我们可以看出:接口就是公共的行为规范,大家在实现时,只要符合标准规范,就可以通用。在Java中,接口可以看成是:多个类的公共规范,是一种引用数据类型。

    语法规则

    接口的定义与定义类的格式基本相同,将class关键换成interface关键字,就定义了一个接口。

    //接口语法规则
    public interface InterfaceName {
        //抽象方法
        public abstract void method1();//public abstract是固定搭配,可以不写
        public void method2();
        abstract void method3();
        void method4();
        //注意接口在上述的描述中都是抽象方法,跟推荐方式4,代码更加简洁明了
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    【提示】

    1. 创建接口的命名一般以大写字母I开头
    2. 接口的命名一般使用“形容词”词性的单词
    3. 阿里编码规范中,接口中的方法和属性不要加任何修饰符号,保持代码的简洁性。

    接口的使用

    接口不能直接使用,必须要有一个“实现类”来“实现”该接口,实现接口中所有的抽象方法。

    public class 类名称 implement 接口名称 {
    //…
    }

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

    //USB接口
    interface USB {
        void openDevice();
        void closeDevice();
    }
    
    //鼠标类,实现USB接口
    class Mouse implements USB {
        @Override
        public void openDevice() {
            System.out.println("打开鼠标~~~");
        }
        @Override
        public void closeDevice() {
            System.out.println("关闭鼠标~~~");
        }
        public void click() {
            System.out.println("鼠标点击~~~");
        }
    }
    
    //键盘类,实现USB接口
    class KeyBoard implements USB {
        @Override
        public void openDevice() {
            System.out.println("打开键盘~~~");
        }
        @Override
        public void closeDevice() {
            System.out.println("关闭键盘~~~");
        }
        public void inPut(){
            System.out.println("键盘输入~~~");
        }
    }
    
    //笔记本类:使用USB接口
    class Computer {
        public void powerOn() {
            System.out.println("打开笔记本电脑~~~");
        }
        public void powerOff() {
            System.out.println("关闭笔记本电脑~~~");
        }
        public void useDevice(USB usb) {
            usb.openDevice();
            if(usb instanceof Mouse) {
                Mouse mouse = (Mouse)usb;
                mouse.click();
            }
            else if(usb instanceof KeyBoard) {
                KeyBoard keyBoard = (KeyBoard) usb;
                keyBoard.inPut();
            }
            usb.closeDevice();
        }
    }
    
    //开始测试
    public class Test {
        public static void main(String[] args) {
            Computer computer = new Computer();
            computer.powerOn();
            //使用鼠标
            computer.useDevice(new Mouse());
            //使用键盘
            computer.useDevice(new KeyBoard());
            computer.powerOff();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70

    在以上代码中,我们通过鼠标、键盘类简单实现了USB接口,,并通过电脑类进行使用。

    接口的特征

    1. 接口类型是一种引用类型,但是不能直接new接口的对象
      在这里插入图片描述
    2. 接口中每一个方法都是public的抽象方法,即接口中的方法会被隐式的指定为 public abstract(不能添加其他修饰符,或者修改)
      在这里插入图片描述
    3. 接口中的方法是不能在接口中实现的,只能由实现中由类来实现。
      在这里插入图片描述
    4. 重写接口中方法时,不能使用默认的权限
    5. 接口中可以含有变量,但是接口中的变量会被隐式的指定为public static final变量
      在这里插入图片描述
    6. 接口中不能有静态代码块和构造方法
    7. 接口虽然不是类,但是接口编译完成后字节码文件的后缀也是.class
    8. 如果类没有实现接口中的所有抽象方法,则类必须设为抽象类
    9. jdk8中:接口还可以包含defaylt方法

    实现多个接口

    在Java中,类和类之间是单继承的,一个类只有一个父类,即Java中不支持多继承,但是一个类可以实现多个接口,以供使用
    【试题】
    下面我们用类表示一组动物,包含猫、鱼、青蛙;同时提供一组接口,分别是”会飞的,会跑的,会游的“

    //下面我们用类表示一组动物,包含猫、鱼、青蛙;同时提供一组接口,分别是”会飞的,会跑的,会游的“
    interface IFlying {
        void fly();
    }
    interface IRunning {
        void run();
    }
    interface ISwimming {
        void swim();
    }
    class Animal{
        protected String name;
    
        public Animal(String name) {
            this.name = name;
        }
    }
    
    //猫
    class Cat extends Animal implements IRunning {
        public Cat(String name) {
            super(name);
        }
    
        @Override
        public void run() {
            System.out.println(this.name + "正在用四条腿跑~~~");
        }
    }
    
    //鱼
    class Fish extends Animal implements ISwimming {
        public Fish(String name) {
            super(name);
        }
    
        @Override
        public void swim() {
            System.out.println(this.name + "正在用尾巴游泳~~~");
        }
    }
    
    //青蛙,能跑,能游
    class Frog extends Animal implements IRunning, ISwimming {
        public Frog(String name) {
            super(name);
        }
        
        @Override
        public void run() {
            System.out.println(this.name + "正在跳~~~");
        }
        
        @Override
        public void swim() {
            System.out.println(this.name + "正在蹬腿游~~~");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58

    注意一个类实现多个接口,每个接口中的抽象方法都要实现,否则类要被设为抽象类
    上面的代码展示了Java面向对象编程中最常见的用法:一个类继承一个父类,同时实现多种接口。
    继承的表达含义是is-a语义,而接口表达的含义是具有XXX特性

    猫是一种动物,具有会跑的特性
    青蛙是一种动物,既跑,也能游
    鸭子也是一种动物,既能跑,也能游,还能飞

    使用接口以后,类的使用这就不必关注具体的类型,而关注具有某种能力

    接口间的继承

    在Java中,类和类直接是单继承的,一个类可以实现多个接口,接口和接口之间可以多继承。即:用接口可以达到多继承的目的。
    接口可以继承一个接口,达到复用的效果。使用sxtends关键字。

    //接口间的继承
    interface IRunning {
        void run();
    }
    interface ISwimming {
        void swim();
    }
    //两栖动物,既能跑,又能游
    interface IAmphibious extends IRunning, ISwimming {
        
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

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

    接口使用实例

    给对象数组排序

    //接口使用示例
    //给对象数组排序
    class Student {
        private String name;
        private int score;
    
        public Student(String name, int score) {
            this.name = name;
            this.score = score;
        }
    
        @Override
        public String toString() {
            return "[" + this.name + ":" + this.score + "]";
        }
    }
    
    public class Test {
        public static void main(String[] args) {
            Student[] students = new Student[] {
                    new Student("张三", 95),
                    new Student("李四", 96),
                    new Student("王五", 97),
                    new Student("赵六", 92),
            };
            Arrays.sort(students);
            System.out.println(Arrays.toString(students));
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    在这里插入图片描述
    仔细思考发现,和普通的整数不一样,两个数之间可以比较大小,而两个学生对象之间要如何比较呢?
    让我们Student类实现Comparable接口,并实现其中的compareTo方法

    //接口使用示例
    //给对象数组排序
    class Student implements Comparable{
        private String name;
        private int score;
    
        public Student(String name, int score) {
            this.name = name;
            this.score = score;
        }
    
        @Override
        public String toString() {
            return "[" + this.name + ":" + this.score + "]";
        }
    
        @Override
        public int compareTo(Object o) {
            Student s = (Student) o;
            if (this.score > s.score) {
                return -1;
            } else if(this.score < s.score) {
                return 1;
            } else {
                return 0;
            }
        }
    }
    
    public class Test {
        public static void main(String[] args) {
            Student[] students = new Student[] {
                    new Student("张三", 95),
                    new Student("李四", 96),
                    new Student("王五", 97),
                    new Student("赵六", 92),
            };
            Arrays.sort(students);
            System.out.println(Arrays.toString(students));
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41

    在这里插入图片描述
    在sort方法中会调用compareTo方法。compareTo的参数是Object,其实传入的是Student类型的对象,然后比较当前对象和参数对象的大小关系,在执行程序,结果就是正确的。
    注意事项】对于sort方法来说,需要传入的数组的每个对象都是“可比较的”,才具有compareTo这样的能力,通过重写compareTo方法的方式,就可以定义比较规则。

    Clonable 接口和深拷贝

    Java中内置一些很有用的接口,Clonable就是其中之一。
    Object类中存在一个clone方法,调用这个方法可以创建一个对象的“拷贝”。但是想合法的调用clone 方法,必须实现Clonable接口,否则就会抛出CloneNotSupportedException异常。

    //Clonable接口
    class Animal implements Cloneable {
        private String name;
    
        @Override
        public Animal clone() {
            Animal o = null;
            try{
                o = (Animal) super.clone();
            } catch (CloneNotSupportedException e) {
                e.printStackTrace();
            }
            return o;
        }
    }
    
    public class Test {
        public static void main(String[] args) {
            Animal animal = new Animal();
            Animal animal2 = animal.clone();
            System.out.println(animal == animal2);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    浅拷贝和深拷贝
    Cloneable拷贝的对象是一份“浅拷贝”
    观察以下代码

    //浅拷贝
    class Money {
        public double m = 80.1;
    }
    
    class Person implements Cloneable {
        public Money money = new Money();
    
        @Override
        protected Object clone()throws CloneNotSupportedException {
            return super.clone();
        }
    }
    
    public class Test {
        public static void main(String[] args)throws CloneNotSupportedException {
            Person person1 = new Person();
            Person person2 = (Person) person1.clone();
            System.out.println(person1.money.m);
            System.out.println(person2.money.m);
            System.out.println("=====================");
            person2.money.m = 20.9;
            System.out.println(person1.money.m);
            System.out.println(person2.money.m);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    在这里插入图片描述
    这里我们通过clone来拷贝对象animal1给animal2引用,但是实际上,我们只拷贝了animal1引用中money的地址,并没有把money中实际的内容拷贝进去,所以出现了连个money引用指向同一对象的问题,后面修改任何一个money的值,都会发生变化。

    //深拷贝
    class Money implements Cloneable {
        public double m = 80.1;
    
        @Override
        protected Object clone()throws CloneNotSupportedException {
            return super.clone();
        }
    }
    
    class Person implements Cloneable {
        public Money money = new Money();
    
        @Override
        protected Object clone()throws CloneNotSupportedException {
            //克隆person对象
            Person person = (Person) super.clone();
            //克隆money
            person.money = (Money) this.money.clone();
            return person;
        }
    }
    
    public class Test {
        public static void main(String[] args)throws CloneNotSupportedException {
            Person person1 = new Person();
            Person person2 = (Person) person1.clone();
            System.out.println(person1.money.m);
            System.out.println(person2.money.m);
            System.out.println("=====================");
            person2.money.m = 20.9;
            System.out.println(person1.money.m);
            System.out.println(person2.money.m);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35

    在这里插入图片描述
    这里我们把money对象再拷贝以下即可实现深拷贝的目的

    抽象类和接口的区别

    抽象类和接口都是Java中多态的常见的使用方式。
    【核心区别】抽象类可以包含普通方法和普通字段,这样的普通方法和字段可以被子类直接使用,而不被重写,而接口中不能包含普通方法,子类必须要重写所有的抽象方法。

    区别抽象类(abstract)接口(interface)
    结构组成普通类和抽象方法抽象方法+全局变量
    权限各种权限public abstract
    子类使用使用extends关键字使用implements关键字
    关系一个抽象类可以实现若干接口接口可以使用extends实现继承多个接口
    子类限制一个子类只能继承一个抽象类一个类可以实现若干接口

    Object

    Object是Java中默认提供的一个类,Java中出了Object类,所有的类都是存在继承关系的,默认继承Object类,所有类的对象都可以使用Object的引用来接收
    示例:使用object接受所有类的对象。
    在这里插入图片描述
    在开发中,Object类是参数的最高统一类型。但是Object类中也存在着一些定义好的方法。如
    在这里插入图片描述
    但是现在我们要熟悉的的有:toString() \ equals() \ hashcode 方法

    获取对象信息(toString)

    如果要打印对象中的内容,我们重写Object 中toString 方法即可

    //toString 
    class Studnet {
        String name;
        int age;
    
        public Studnet(String name, int age) {
            this.name = name;
            this.age = age;
        }
        @Override
        public String toString() {
            return name + " " + age;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    这样就能按照自己的想法的到想的内容;
    我们看看原来的toString所放的内容
    在这里插入图片描述
    得到的是 类名 + @ + 类似于地址的字符串

    对象比较equals方法

    在Java中,== 进行比较时:

    • 如果是基本数据类型,比较的是变量中的值;
    • 如果是引用数据类型,比较的是引用的地址;
    • 如果我们要比较对象中的内容,我们要重写Object中equals方法,因为equals方法默认也是按照地址比较。
    //equals
    class Student {
        String name;
        int age;
    
        public Student(String name, int age) {
            this.name = name;
            this.age = age;
        }
        @Override
        public boolean equals(Object obj) {
           if(obj == null) {
               return false;
           }
           if(this == obj) {
               return true;
           }
           if(!(obj instanceof Student)) {
               return true;
           }
           Student s = (Student) obj;
           return this.name.equals(s.name) && this.age == s.age;
    
    
        }
        @Override
        public String toString() {
            return name + " " + age;
        }
    }
    public class Test {
        public static void main(String[] args) {
            Student s1 = new Student("xiaohong", 9);
            Student s2 = new Student("xiaohong", 9);
            System.out.println(s1.equals(s2));
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37

    这里我们比较了这个对象的所有内容,全部相等,代表他们相等。

  • 相关阅读:
    逆向工程:Python反编译工具的一点介绍(如何还原pyc文件)
    第六十二天 牛客62场小白月赛
    Git学习笔记(五)IDEA使用Git
    大模型赛道如何实现华丽的弯道超车
    Bentley OpenFlows FLOOD 集成的洪水模拟软件
    Meetup 回顾|Data Infra 研究社第十六期(含资料发布)
    淘宝店铺订单解密接口/淘宝店铺订单插旗接口/淘宝店铺订单交易接口/淘宝店铺商品上传接口/淘宝店铺订单明文接口/代码对接分享
    C#题库(选择题,填空题,判断题,编程题)
    win11无损关闭系统更新
    linux loglevel
  • 原文地址:https://blog.csdn.net/fengxia110/article/details/128005332