目录
1.接口的概念
2.语法规则
3.接口使用
4.接口特性
5.实现多个接口
6.接口间的继承
7.接口使用实例
1.接口的概念
电脑的USB口上,可以插:U盘、鼠标、键盘等所有符合USB协议的设备;数据线的type-c口上,可以插手机,蓝牙耳机充电盒等所有符合规范的设备。由此可以看出:接口就是公共行为的规范表准,在使用时,只要符合规范就可以使用,在Java中,接口可以看成是多个类的公共规范,是一种引用数据类型。
2.语法规则
接口的定义格式与定义类的格式基本相同,将class关键字换成 interface 关键字,就定义了一个接口。
public interface 接口名{
//抽象方法
public abstract void method1(); //在接口中public abstract是固定搭配,可以省略不写 public void method2();
abstract void method3();
void method4(); //以上几种定义方法的方式都可以
}
提示:创建接口时,一般以大写字母I开头来命名,命名一般用“形容词”词性的单词,接口中的方法和属性不要加任何修饰符号,保持代码简洁
3.接口使用
接口不能直接使用,必须要有一个"实现类"来"实现"该接口,实现接口中的所有抽象方法。
public class 类名 implements 接口名{
//...
}
注意:子类和父类之间是extends 继承关系,类与接口之间是 implements 实现关系。
请实现笔记本电脑使用USB鼠标、USB键盘的例子
1. USB接口:包含打开设备、关闭设备功能
2. 笔记本类:包含开机功能、关机功能、使用USB设备功能
3. 鼠标类:实现USB接口,并具备点击功能
4. 键盘类:实现USB接口,并具备输入功能
//USB接口 public interface USB {//打开设备void openDevicce();//关闭设备void offDevicce(); }//鼠标类,实现USB接口 public class Mouse implements USB{@Overridepublic void openDevicce() {System.out.println("连接鼠标设备成功");}@Overridepublic void offDevicce() {System.out.println("鼠标设备断开连接");}//鼠标点击public void click(){System.out.println("鼠标点击成功~");} }//键盘类,实现USB接口 public class KeyBoard implements USB{@Overridepublic void openDevicce() {System.out.println("连接键盘设备成功");}@Overridepublic void offDevicce() {System.out.println("键盘设备断开连接");}//输入功能public void input(){System.out.println("键盘输入");} }//电脑类, public class Computer {//开机public void openComputer(){System.out.println("打开电脑");}//关机public void offComputer(){System.out.println("关闭电脑");}//使用USB接口设备public void useDevicce(USB usb){usb.openDevicce();if (usb instanceof Mouse){Mouse mouse= (Mouse)usb;mouse.click();}if (usb instanceof KeyBoard){KeyBoard keyBoard=(KeyBoard)usb;keyBoard.input();}usb.offDevicce();} }//测试类
public class Text {public static void main(String[] args) {//实例化电脑Computer computer=new Computer();//打开电脑computer.openComputer();System.out.println("====");//使用鼠标设备computer.useDevicce(new Mouse());System.out.println("====");//使用键盘设备computer.useDevicce(new KeyBoard());//关闭电脑computer.offComputer();}}
4.接口特性
1. 接口类型是一种引用类型,但不能直接new接口的对象。
public class TestUSB {
public static void main(String[] args) {
USB usb = new USB();
}
} //编译报错,USB是抽象类型,无法实例化
2.接口中每一个方法都是public的抽象方法, 即接口中的方法会被隐式的指定为 public abstract(只能是public abstract,其他修饰符都会报错)。
public interface USB {
private void openDevice(); // 编译 报错,不允许使用修饰符private
void closeDevice();
}
3.接口中的方法是不能在接口中实现的,只能由实现接口的类来实现。
public interface USB {
void openDevice();
void closeDevice(){
System.out.println("关闭USB设备");
}// 编译报错,因为接口中的方法默认为抽象方法,不能带有方法体
}
4. 重写接口中方法时,不能使用默认的访问权限。
public interface USB {
//打开设备
void openDevicce();
//关闭设备
void offDevicce();
}
public class Mouse implements USB{
@Override
void openDevicce() {
System.out.println("连接鼠标设备成功");
} //编译报错,重写时不能使用默认修饰符
5. 接口中可以含有变量,但是接口中的变量会被隐式的指定为 public static final 变量。
public interface USB {int a=1;//默认被 final public static 修饰//打开设备void openDevicce();//关闭设备void offDevicce(); }public class Text {public static void main(String[] args) {System.out.println(USB.a); //可以通过接口访问,说明是静态的System.out.println(a); //可以直接访问,说明是公开的USB a=10; //编译报错,说明a具有final属性} }
6. 接口中不能有静态、动态代码块和构造方法。
public interface USB {
public USB(){
} //编译报错{
} // 编译报错static{
} //编译报错
void openDevice();
void offDevice();
}
7. 接口虽然不是类,但接口编译完成后字节码文件的后缀格式也是.class。
8. 如果类没有实现接口中的所有抽象方法,则类必须设为抽象类。
9.jdk8中:接口中还可以包含default方法。
5.实现多个接口
在Java中,类和类之间是单继承的,一个类只能有一个父类,即Java中不支持多继承,但是一个类可以实现多个接口。下面通过类来表示一组动物。
//动物类 public class Animals {protected String name;protected int age;public Animals(String name, int age) {this.name = name;this.age = age;} }
有的动物会飞,有的动物会跑,有的动物会游泳,还有的动物可能有这三种中的多种,可以设为接口。
//接口,分别表示会飞的、会跑的、会游泳的 interface Flying{void fly(); } interface Running{void running(); }interface Swimming{void swimming(); }
下面创建具体的动物。
猫,是一种会跑的动物。
//猫类 public class Cats extends Animals implements Running{public Cats(String name, int age) {super(name, age);}@Overridepublic void running() {System.out.println(this.name+"用四只腿跑~");} }
鱼,是一种会游的动物。
public class Fish extends Animals implements Swimming{public Fish(String name, int age) {super(name, age);}@Overridepublic void swimming() {System.out.println(this.name+"用尾巴游泳");} }
青蛙,是一种既能跑又能游的两栖动物。
//青蛙类 public class Frog extends Animals implements Running,Swimming{public Frog(String name, int age) {super(name, age);}@Overridepublic void running() {System.out.println(this.name+"可以用两只脚跳");}@Overridepublic void swimming() {System.out.println(this.name+"可以用两只脚两只手游");} }
注意:一个类实现多个接口时,每个接口中的抽象方法都要实现,否则类必须设置为抽象类。(IDEA 中使用 ctrl + i 快速实现接口)
鸭子,是一种海陆空三栖动物,既可以跑又可以游还能飞。
//鸭子类 public class Duck extends Animals implements Flying,Running,Swimming{public Duck(String name, int age) {super(name, age);}@Overridepublic void fly() {System.out.println(this.name+"可以用两个翅膀飞");}@Overridepublic void running() {System.out.println(this.name+"可以两只脚跑");}@Overridepublic void swimming() {System.out.println(this.name+"可以用两只脚和两个翅膀游");} }
//测试 public class text {public static void main(String[] args) {Cats cat=new Cats("小猫",5);cat.running();System.out.println("====");Fish fish=new Fish("小鱼",2);fish.swimming();System.out.println("====");Frog frog=new Frog("小青蛙",3);frog.running();frog.swimming();System.out.println("====");Duck duck=new Duck("小鸭子",6);duck.fly();duck.running();duck.swimming();} }
上面的代码展示了 Java 面向对象编程中最常见的用法: 一个类继承一个父类, 同时实现多种接口。继承表达的含义是 is - a 语义, 而接口表达的含义是 具有 xxx 特性。如上述的猫,是一种动物,具有跑的特性;鱼,是一种动物,具有在水中游的特性等等。
6.接口间的继承
在Java中,类和类之间是单继承的,一个类可以实现多个接口,接口与接口之间可以多继承。即:用接口可以达到多继承的目的。接口可以继承一个接口, 达到复用的效果. 使用 extends 关键字。
例如
//接口,表示跑 interface Running{void run(); } //接口,表示游 interface Swimming{void swimming(); } //接口,表示两栖动物(既能跑又能游),这里extends表示拓展 interface Amphibious extends Running,Swimming{}//青蛙类 class Frog implements Amphibious{//... }
此时实现接口创建的 Frog 类, 就继续要实现 run 方法, 也需要实现 swim 方法。接口间的继承相当于把多个接口合并在一起。
7.接口使用实例
给对象数组排序
public class Students {private String name;private int age;public Students(String name, int age) {this.name = name;this.age = age;}@Overridepublic String toString() {return "Students{" +"name='" + name + '\'' +", age=" + age +'}';}}
定义一个学生数组对象并对数组中的元素进行排序
Students[] students=new Students[3]; students[0]=new Students("张三",15); students[1]=new Students("李四",10); students[2]=new Students("王五",30);
,之前我们学过,数组自带有排序方法,是否可以直接使用这个方法呢?
Arrays.sort(students); System.out.println(Arrays.toString(students));
我们会发现,编译通过,但运行报错。仔细一想,之前数组中每一个元素是整数,可以直接比较大小,而在这里,数组中的元素为一个个的学生,而两个学生的大小关系无法确定,需要我们额外指定比较方式。
让我们的 Students 类实现 Comparable 接口, 并实现其中的 compareTo 方法
public class Students implements Comparable(也可以写成Comparable<T>,T表示要比较的数据类型) { //表示当前的类是可以比较的private String name;private int age;public Students(String name, int age) {this.name = name;this.age = age;}@Overridepublic String toString() {return "{"+"name=" + name +", age=" + age+"}";}//重写字符串比较函数@Override //Object类型的变量opublic int compareTo(Object o) {Students s=(Students)o;//强制类型转换/*if(this.age>s.age){return 1;} else if (this.age<s.age) {return -1;}else {return 0;}*/return this.age-s.age;} }
在 sort 方法中会自动调用 compareTo 方法. compareTo 的参数是 Object , 其实传入的就是 Student 类型的对象 。然后比较当前对象和参数对象的大小关系(按年龄计算):如果当前对象应排在参数对象之前, 返回小于 0 的数字;如果当前对象应排在参数对象之后, 返回大于 0 的数字;如果当前对象和参数对象不分先后, 返回 0;
import java.util.Arrays; public class Text {public static void main(String[] args) {Students[] students=new Students[3];students[0]=new Students("张三",15);students[1]=new Students("李四",10);students[2]=new Students("王五",30);Arrays.sort(students);System.out.println(Arrays.toString(students));} }
注意:对于 sort 方法来说, 需要传入的数组的每个对象都是 "可比较" 的, 需要具备 compareTo 这样的能力. 通过重写 compareTo 方法的方式, 就可以定义比较规则。这种对类的入侵性比较强,一旦写好规定的比较方式,那么以后只能以这种方式比较。
第二种方式,构造比较器类
public class Students {public String name;public int age;public Students(String name, int age) {this.name = name;this.age = age;}@Overridepublic String toString() {return "{" +"name=" + name +", age=" + age +"}";} }//比较器 class ageComparator implements Comparator<Students> {@Overridepublic int compare(Students o1,Students o2) {return o1.age- o2.age;} } class nameComparator implements Comparator<Students>{@Overridepublic int compare(Students o1, Students o2) {//String 自己重写compareTo 方法return o1.name.compareTo(o2.name);} } public class Text {public static void main(String[] args) {Students[] students=new Students[3];students[0]=new Students("zhangsan",15);students[1]=new Students("lisi",10);ageComparator ageComparator1=new ageComparator();System.out.println(ageComparator1.compare(students[0],students[1]));System.out.println("=====");nameComparator nameComparator1=new nameComparator();System.out.println(nameComparator1.compare(students[0],students[1]));} }
注意:这种方式做到灵活比较,只需传两个对象即可。