Java接口的相关知识

45 篇文章 0 订阅
1 篇文章 0 订阅

接口的概念

在生活中,接口的例子比比皆是,比如,电脑上的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. 创建接口的命名一般以大写字母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();
    }
}

在以上代码中,我们通过鼠标、键盘类简单实现了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 + "正在蹬腿游~~~");
    }
}

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

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

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

接口间的继承

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

//接口间的继承
interface IRunning {
    void run();
}
interface ISwimming {
    void swim();
}
//两栖动物,既能跑,又能游
interface IAmphibious extends IRunning, ISwimming {
    
}

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

接口使用实例

给对象数组排序

//接口使用示例
//给对象数组排序
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));
    }
}

在这里插入图片描述
仔细思考发现,和普通的整数不一样,两个数之间可以比较大小,而两个学生对象之间要如何比较呢?
让我们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));
    }
}

在这里插入图片描述
在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);
    }
}

浅拷贝和深拷贝
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);
    }
}

在这里插入图片描述
这里我们通过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);
    }
}

在这里插入图片描述
这里我们把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;
    }
}

这样就能按照自己的想法的到想的内容;
我们看看原来的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));
    }
}

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值