📚 目录
- [1. 什么是接口?](#1. 什么是接口?)
1.1接口的概念 - [2. 接口的语法规则](#2. 接口的语法规则)
2.1单个接口的使用
2.2接口的特性
2.3多个接口的使用 - 3.接口间的继承
- 4.接口的实例
4.1Comparable接口的使用
4.2Comparator接口的使用
前言:
很多初学者初识接口时,总会疑惑:既然有了抽象类,为什么还需要接口?接口和继承到底有什么区别?如何用接口写出更灵活、易维护的代码?其实,接口的核心价值,从来不是「实现功能」,而是规范行为、抽象能力、解耦依赖------ 它是 Java 「面向接口编程」思想的核心载体,也是从基础编程进阶到优雅架构设计的必经之路。
1. 什么是接口?
1.1 接口的概念
接口这个概念距离我们很近,像我们的电脑接口,手机充电接口,三角插排的口,充电口等等,只要符合规范,能插得进去我们都能够使用。
** Java中接口可以理解为:多个类的公共规范,是一种数据类型。**
我们学习了继承这个概念,知道了父子类的关系,那么为什么要使用接口这个概念呢?
** 父类是子类共有的性质,而不是单一的;子类只要满足条件,都能继承父类。
接口:一个类可以实现多个接口,弥补单继承的不足。**
** 简单说:接口定规矩,类来做实现。**
想象一下:如果有一个Animal的类,里面有跑、飞、游泳等等方法,如果一只狗继承了Animal这个类,狗也能够飞?
这不现实。而接口中写了跑的方法,只要满足跑这个方法都能进行调用。
[🔙 返回目录](#🔙 返回目录)
2. 接口的语法规则
关键字:interface
java
public interface 接口名字 {
//抽象方法以及成员
}
创建接口:
java
public interface IUSB {
public static final int a =10;
public abstract void openEquipment();
public abstract void closeEquipment();
}
注意:
** public static final 是固定搭配的,编译器默认的,可以不写。
public abstract 是固定搭配,编译器默认的,可以不写。**
java
public interface IUSB {
int a =10;
void openEquipment();//推荐使用这种,代码比较简洁
void closeEquipment();
}
小贴士:
** 一般接口名字以大写字面 I 开头。
命名一般使用形容词,方便理解。
阿里巴巴中规定:接口中的方法不要使用加任何的修饰符,保持代码的简洁性。**
[🔙 返回目录](#🔙 返回目录)
2.1单个接口的使用
关键字:implements
类与接口的关系用implements连接。
USB接口:
java
public interface IUSB {
void openEquipment();
void closeEquipment();
}
键盘接口:
java
public class Keyboard implements IUSB{
@Override
public void openEquipment() {
System.out.println("使用键盘输入中...");
}
@Override
public void closeEquipment() {
System.out.println("断开键盘接口的连接...");
}
}
鼠标接口:
java
public class Mouse implements IUSB{
@Override
public void openEquipment() {
System.out.println("使用鼠标点击东西...");
}
@Override
public void closeEquipment() {
System.out.println("断开鼠标的连接...");
}
}
使用Test类调用各个接口:
java
public class Test {
public static void Use(IUSB iusb) {
iusb.openEquipment();
iusb.closeEquipment();
}
public static void main(String[] args) {
Keyboard keyboard = new Keyboard();
Mouse mouse = new Mouse();
Use(keyboard);
System.out.println("============");
Use(mouse);
}
}

单一接口的使用很简单,基本上和类差不多。
** 我们在Use方法中参数为IUSB类型的iusb ,接受了键盘和鼠标的对象,这一过程就是向上转型。
通过iusb调用不同类的方法,发生了动态绑定,产生了不同的结果。
所以接口也能发生多态。**
[🔙 返回目录](#🔙 返回目录)
2.2接口的特性
** 接口是一种引用类型,不能创建变量。**

** 接口中的变量不管你写不写public static final编译器默认都是它,不能修改。且只能是public,不能是其他的访问权限。**

** Java8中接口中规定:方法只能为能为public abstract修饰。**

** Java8中可以有default修饰的的方法。**

** 重写的方法不能是默认访问权限。**

接口不同于类,接口不允许出现构造方法和静态代码。

[🔙 返回目录](#🔙 返回目录)
2.3多个接口的使用
** Java中不能多继承,而类可以连接多个接口。**
我们知道狗是不能飞的,鸟可以飞,如果都继承了Animal这个类就显得很不合理了。
我们可以使用接口将他们分开,满足条件就能够使用。
定义3个接口
java
public interface IRunning {
void run();
}
java
public interface IJump {
void jump();
}
java
public interface IFly {
void fly();
}
定义一个父类:
java
public abstract class Animal {
public String name;
public abstract void eat();
public Animal(String name) {
this.name = name;
}
}
创建2个子类并继承Animal父类,接上对应的特性。
java
public class Dog extends Animal implements IJump,IRunning{
public Dog(String name) {
super(name);
}
@Override
public void eat() {
System.out.println(this.name+"正在吃狗粮...");
}
@Override
public void jump() {
System.out.println(this.name+"正在跳...");
}
@Override
public void run() {
System.out.println(this.name+"正在使用四肢跑....");
}
}
java
public class Bird extends Animal implements IFly,IJump{
public Bird(String name) {
super(name);
}
@Override
public void eat() {
System.out.println(this.name+"正在抓虫吃...");
}
@Override
public void fly() {
System.out.println(this.name+"正在飞...");
}
@Override
public void jump() {
System.out.println(this.name+"正在跳...");
}
}

** 有了接口,我们就不需要关注它是什么东西,我们只需要关注,它是否具备这一个特性就行了。**
[🔙 返回目录](#🔙 返回目录)
3. 接口间的继承
** 接口与接口之间也能相互继承,达到代码的复用。语法格式与类相同。**
以上面代码为例:
java
public interface ICombine extends IJump,IRunning {
@Override
void jump();
@Override
void run();
}
** 继承了跑和跳的功能。
我们可以通过不同的接口,组合出各种各样功能的接口。**
** 我们可以使用接口来模拟类的多继承。**
[🔙 返回目录](#🔙 返回目录)
4. 接口的使用
4.1Comparable接口的使用
注意事项:

** 使用Comparable的时候如果没写的时候,编译器会默认认为你是想要object的。**

** 使用的时候我们需要重写它的方法。**
java
public class Student implements Comparable<Student>{
public String name;
public int age;
public double score;
public Student(String name, int age, double score) {
this.name = name;
this.age = age;
this.score = score;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
", score=" + score +
'}';
}
//重写的comparabTo方法
@Override
public int compareTo(Student o) {
Student s = (Student)o;
if (this.score > s.score) {
return -1;
} else if (this.score < s.score) {
return 1;
} else {
return 0;
}
}
}
** 我们使用它的时候有个弊端,也就是只能用年龄去比,不好修改。
如果在公司里强行修改的花,可能会出现一系列的bug。**
[🔙 返回目录](#🔙 返回目录)
4.2Comparator接口的使用
Comparator接口完美解决了我们这个问题。
使用注意事项:
和Comparable一下需要我们重写方法。

我们重新写3个方法:
java
public class IAgeCompara implements Comparator<Student> {
@Override
public int compare(Student o1, Student o2) {
return o1.age - o2.age;
}
}
java
public class ScoreCompara implements Comparator<Student> {
@Override
public int compare(Student o1, Student o2) {
return (int) (o1.score - o2.score);
}
}
虽然精度会丢失,但是主要为了测试和使用。

那名字怎么比呢?名字肯定不能相减。

** 我们发现String里面接了Comparable这个接口。**

我们就能这么写。
java
public class INameCompara implements Comparator<Student> {
@Override
public int compare(Student o1, Student o2) {
return o1.name.compareTo(o2.name);
}
}
java
public class Test {
public static void main(String[] args) {
Student[] student = new Student[3];
student[0] = new Student("zhangsan",29,88.9);
student[1] = new Student("lisi",43,68.9);
student[2] = new Student("wangwu",19,98.9);
System.out.println(student[0]);
INameCompara nameCompara = new INameCompara();
IAgeCompara iAgeCompara = new IAgeCompara();
ScoreCompara scoreCompara = new ScoreCompara();
System.out.println("使用名字排序");
Arrays.sort(student,nameCompara);
System.out.println(Arrays.toString(student));
System.out.println("使用年龄排序");
Arrays.sort(student,iAgeCompara);
System.out.println(Arrays.toString(student));
System.out.println("使用分数排序");
Arrays.sort(student,scoreCompara);
System.out.println(Arrays.toString(student));
}
}

[🔙 返回目录](#🔙 返回目录)