目录
1.接口的概念
2.语法规则
3.接口使用
4.接口特性
5.实现多个接口
6.接口间的继承
7.接口使用实例
电脑的USB口上,可以插:U盘、鼠标、键盘等所有符合USB协议的设备;数据线的type-c口上,可以插手机,蓝牙耳机充电盒等所有符合规范的设备。由此可以看出:接口就是公共行为的规范表准,在使用时,只要符合规范就可以使用,在Java中,接口可以看成是多个类的公共规范,是一种引用数据类型。
接口的定义格式与定义类的格式基本相同,将class关键字换成 interface 关键字,就定义了一个接口。
public interface 接口名{
//抽象方法
public abstract void method1(); //在接口中public abstract是固定搭配,可以省略不写 public void method2();
abstract void method3();
void method4(); //以上几种定义方法的方式都可以
}
提示:创建接口时,一般以大写字母I开头来命名,命名一般用“形容词”词性的单词,接口中的方法和属性不要加任何修饰符号,保持代码简洁
接口不能直接使用,必须要有一个"实现类"来"实现"该接口,实现接口中的所有抽象方法。
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{ @Override public void openDevicce() { System.out.println("连接鼠标设备成功"); } @Override public void offDevicce() { System.out.println("鼠标设备断开连接"); } //鼠标点击 public void click(){ System.out.println("鼠标点击成功~"); } }//键盘类,实现USB接口 public class KeyBoard implements USB{ @Override public void openDevicce() { System.out.println("连接键盘设备成功"); } @Override public 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(); } }
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方法。
在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); } @Override public void running() { System.out.println(this.name+"用四只腿跑~"); } }
鱼,是一种会游的动物。
public class Fish extends Animals implements Swimming{ public Fish(String name, int age) { super(name, age); } @Override public void swimming() { System.out.println(this.name+"用尾巴游泳"); } }
青蛙,是一种既能跑又能游的两栖动物。
//青蛙类 public class Frog extends Animals implements Running,Swimming{ public Frog(String name, int age) { super(name, age); } @Override public void running() { System.out.println(this.name+"可以用两只脚跳"); } @Override public 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); } @Override public void fly() { System.out.println(this.name+"可以用两个翅膀飞"); } @Override public void running() { System.out.println(this.name+"可以两只脚跑"); } @Override public 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 特性。如上述的猫,是一种动物,具有跑的特性;鱼,是一种动物,具有在水中游的特性等等。
在Java中,类和类之间是单继承的,一个类可以实现多个接口,接口与接口之间可以多继承。即:用接口可以达到多继承的目的。接口可以继承一个接口, 达到复用的效果. 使用 extends 关键字。
例如
//接口,表示跑 interface Running{ void run(); } //接口,表示游 interface Swimming{ void swimming(); } //接口,表示两栖动物(既能跑又能游),这里extends表示拓展 interface Amphibious extends Running,Swimming{ }//青蛙类 class Frog implements Amphibious{ //... }
此时实现接口创建的 Frog 类, 就继续要实现 run 方法, 也需要实现 swim 方法。接口间的继承相当于把多个接口合并在一起。
给对象数组排序
public class Students { private String name; private int age; public Students(String name, int age) { this.name = name; this.age = age; } @Override public String toString() { return "Students{" + "name='" + name + '\'' + ", age=" + age + '}'; } }
定义一个学生数组对象并对数组中的元素进行排序
Students[] students=new Students[3]; students[0]=new Students("zhangsan",15); students[1]=new Students("lisi",10); students[2]=new Students("wangwu",30);
,之前我们学过,数组自带有排序方法,是否可以直接使用这个方法呢?
Arrays.sort(students); System.out.println(Arrays.toString(students));
我们会发现,编译通过,但运行报错。仔细一想,之前数组中每一个元素是整数,可以直接比较大小,而在这里,数组中的元素为一个个的学生,而两个学生的大小关系无法确定,需要我们额外指定比较方式。
让我们的 Students 类实现 Comparable 接口, 并实现其中的 compareTo 方法
public class Students implements Comparable(也可以写成Comparable,T表示要比较的数据类型) { //表示当前的类是可以比较的 private String name; private int age; public Students(String name, int age) { this.name = name; this.age = age; } @Override public String toString() { return "{"+ "name=" + name + ", age=" + age+ "}"; } //重写字符串比较函数 @Override //Object类型的变量o public int compareTo(Object o) { Students s=(Students)o;//强制类型转换 /*if(this.age>s.age){ return 1; } else if (this.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; } @Override public String toString() { return "{" + "name=" + name + ", age=" + age + "}"; } }//比较器 class ageComparator implements Comparator{ @Override public int compare(Students o1,Students o2) { return o1.age- o2.age; } } class nameComparator implements Comparator { @Override public 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(); Arrays.sort(students,ageComparator1); System.out.println(Arrays.toString(students)); System.out.println("====="); nameComparator nameComparator1=new nameComparator(); Arrays.sort(students,nameComparator1); System.out.println(Arrays.toString(students)); } }
注意:这种方式做到灵活比较,想用那种方式就调用哪种方式。