目录
- 1、接口的概念
- 2、语法规则
- 2.1 接口的定义
- 2.2、接口的使用
- 3、特性
- 4、实现多个接口
- 5、接口中的继承
- 6、接口使用实例
1、接口的概念
在现实生活中,接口的例子有很多,比如:笔记本的 USB 接口,电源插座等。在电脑的 USB 口上,可以插鼠标、键盘等符合 USB 协议的设备;在电源插座上,可以插电脑、电视机等符合插座规范的设备。
通过上述例子可以看出:接口是公共的行为规范标准,在实现时,只要符合规范标准,就可以通用。因此在 Java 中,接口可以定义为:多个类的公共规范,是一种引用数据类型。
2、语法规则
2.1 接口的定义
接口的定义格式和类的定义格式基本相同,只是将 class 关键字换成 interface 关键字。
public interface 接口名称 {// 变量变量类型 变量名 = 变量值;// 抽象方法void method();
}
- 接口中抽象方法默认搭配是 public abstract,建议不写,保持代码的简洁性。
- 创建接口时,接口的命名一般以大写字母 I 开头,一般使用形容词词性的单词。
- 接口中的变量被隐式指定为 public static final 变量。
2.2、接口的使用
接口不能直接使用,必须要有一个“实现类”来实现接口,且实现接口中的所有抽象方法。
public class 类名称 implements 接口名称 {//...
}
以电脑上的 USB 接口为例,鼠标和键盘均插入该 USB 接口。
// IUSB 接口
public interface IUSB {void openUSBDevice();void closeUSBDevice();
}// 键盘类实现 USB 接口
public class KeyBoard implements IUSB{// 在 IDEA 中,按 Ctrl+I 可以快速重写接口中的方法@Overridepublic void openUSBDevice() {System.out.println("打开键盘");}public void input(){System.out.println("通过键盘进行输入");}@Overridepublic void closeUSBDevice() {System.out.println("关闭键盘");}
}// 鼠标类实现 USB 接口
public class Mouse implements IUSB{@Overridepublic void openUSBDevice(){System.out.println("打开鼠标");}public void click(){System.out.println("鼠标点击");}@Overridepublic void closeUSBDevice(){System.out.println("关闭鼠标");}
}// 电脑类中使用 USB 接口
public class Computer {public void powerOn(){System.out.println("开机...");}public void powerOff(){System.out.println("关机...");}public void useUSBDevice(IUSB usb){usb.openUSBDevice();// 向下转型不安全// Mouse mouse = (Mouse) usb;// 使用 instanceof if(usb instanceof Mouse){Mouse mouse = (Mouse) usb;mouse.click();}else if(usb instanceof KeyBoard){KeyBoard keyBoard = (KeyBoard)usb;keyBoard.input();}usb.closeUSBDevice();}
}// 测试电脑类
public class TestComputer {public static void main(String[] args) {// 注意:接口的引用可以指向任意实现该接口的对象// 接口的引用可以指向不同实现类的对象,因此就可以实现多态// IUSB usb = new Mouse();// IUSB usb = new KeyBoard();Computer computer = new Computer();computer.powerOn();computer.useUSBDevice(new Mouse());computer.useUSBDevice(new KeyBoard());computer.powerOff();}
}
输出:
3、特性
- 接口类型是一种引用类型,但是不能直接 new 接口的对象。
- 接口的方法都被隐式指定为 public abstract 类型,使用其他修饰符会报错。
- 接口中的变量都被隐式指定为 public static final 类型。
- 接口中的方法是抽象方法,不能在接口中实现,只能由实现接口的实现类来实现。
- 在类中重写接口中的方法时,必须使用 public 修饰符来修饰。这是因为重写的方法的修饰符优先级必须高于等于原方法,而接口中的抽象方法默认是 public,因此实现类中重写抽象方法时修饰符只能用 public。
- 接口中不能有静态代码块、实例代码块和构造方法。
- 接口虽然不是类,但是编译后仍然会生成字节码文件,且后缀仍然是 .class。
- 如果类没有实现接口中的所有抽象方法,那么类必须定义为抽象类。
- jdk8 中:接口中还可以包含 default 方法,便于接口的更新。
4、实现多个接口
在 Java 中,类和类之间是单继承的,一个类只能有一个基类,即不支持多继承,但是一个类可以实现多个接口。
// 动物类
public abstract class Animal {protected String name;protected String gender;protected int age;// 所有的动物都需要吃饭睡觉,这些是动物的公共方法public abstract void eat();public abstract void sleep();
}// 会飞的接口
public interface IFlying {void fly();
}
// 会跑的接口
public interface IRunning {void run();
}
// 会游泳的接口
public interface ISwimming {void swim();
}// 狗是动物,既会跑,又会游泳
public class Dog extends Animal implements IRunning , ISwimming{@Overridepublic void eat() {System.out.println(name + "在吃骨头~~~");}@Overridepublic void sleep() {System.out.println(name + "睡觉呼呼呼~~~");}@Overridepublic void run() {System.out.println(name + "用四个蹄子跑~~~");}@Overridepublic void swim() {System.out.println(name + "狗刨式~~~");}
}// 鱼是动物,只会游泳
public class Fish extends Animal implements ISwimming {@Overridepublic void eat() {System.out.println(name + "吃泥鳅~~~");}@Overridepublic void sleep() {System.out.println(name + "睁着眼睛睡觉~~~");}@Overridepublic void swim() {System.out.println(name + "水中自由翱翔~~~");}
}
5、接口中的继承
在 Java 中接口与接口之间可以继承,也可以多继承,从而可以用接口达到多继承的目的。
// 两栖的接口
public interface IAmphibious extends IRunning,ISwimming {}// 青蛙是两栖的
public class Frog implements IAmphibious {@Overridepublic void run() {System.out.println("用腿蹦");}@Overridepublic void swim() {System.out.println("用脚蹬");}
}
接口的继承相当于把多个接口合并在一起。
6、接口使用实例
可以利用 Arrays 的 sort 函数对数组进行排序。
public class TestInt {public static void main(String[] args) {int[] array = {4,9,1,8,0,5,7,3,2,6};// 对array数组进行排序Arrays.sort(array);for (int j : array) {System.out.print(j + " ");}System.out.println();// 输出:0 1 2 3 4 5 6 7 8 9 }
}
同样的,我们想要利用 Arrays 的 sort 函数对学生排序,但是尝试同样的方法会报错。
public class Student{String name;int score;public Student(String name, int score) {this.name = name;this.score = score;}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);for (int i = 0; i < students.length; i++) {System.out.println(students[i]);}}
}
报错原因在于我们没有实现比较器,而利用 Arrays 的 sort 函数进行排序的对象要求必须实现比较器,即是可比较的。
public class Student implements Comparable<Student>{String name;int score;public Student(String name, int score) {this.name = name;this.score = score;}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);for (int i = 0; i < students.length; i++) {System.out.println(students[i]);}}@Overridepublic int compareTo(Student o) {// 用 this 和 o 引用的对象的某些字段进行比较return score - o.score;}// 这里要重写 toString 方法,根据需要得到我们想要的输出@Overridepublic String toString() {return "[" + name + "," + score + "]";}
}
输出:
那么 sort 函数里面是如何工作的,我们可以自己实现冒泡排序。
public class Util {// 冒泡排序// 注意:通过sort方法进行排序时,传进来的元素必须要实现Comparable接口的方法public static void sort(Comparable[] c){// 外循环表示冒泡的趟数for (int i = 0; i < c.length-1; i++) {// 具体冒泡的方式:用相邻的两个元素去比较for (int j = 0; j < c.length - 1 - i; j++) {// 这里的 c 可以引用任何实现该接口的对象// 这里的排序方式是升序if(c[j].compareTo(c[j+1]) >= 0){Comparable temp = c[j];c[j] = c[j+1];c[j+1] = temp;}}}}
}