接口(interface)
**定义:**接口类似于一种特殊的抽象类,它是众多抽象方法的集合。
类描述的是对象的属性和方法,接口则是主要包含了类要实现的方法。当一个类实现了接口后,就要实现该接口中所有方法,否则该类就必须声明为抽象类。
接口的成员特点
- 成员变量:只能是常量,默认加入三个关键字(public , static , final)(这三个关键字没有顺序关系)
- 构造方法:没有构造方法
- 成员方法:只能是抽象方法,默认修饰符public abstract
接口的特性
接口中的每个方法都是隐式抽象的,这些方法默认会被隐式地指定为public abstract(只能是public abstract,在JDK 9之前,使用其他修饰符会报错);
即使在接口中定义了变量,默认也会变成常量,因为接口中的变量自动就会被public static final隐式地修饰(接口中变量与常量的修饰符,只能是public,用private修饰会报编译错误);
JDK 8之前,接口中的方法默认是没有实现的,只能由实现该接口的类来实现接口中的方法。从JDK 8开始,接口中可以有默认的default实现方法;允许定义静态方法。
JDK 9开始,接口中允许将方法定义为private,使得某些复用的代码不会把方法暴露出去。
(接口与接口可以多继承)
重写接口中方法是应注意:
- 一个类在实现接口里的方法时,不能抛出强制性的异常,只能在接口或者继承接口的抽象类中抛出该强制性异常;
- 一个类在方法重写时要保持一致的方法名,且两者之间应该保持相同或者相兼容的返回值类型;
- 如果一个抽象类实现接口,该类没必要实现此接口里的方法。
接口的好处
- 弥补了类单继承的不足,一个类可以同时实现多个接口
- 可以让程序面向接口编程,使程序员可以灵活方便的切换各种业务实现
接口和类的关系
- 类和接口:实现关系,可以单实现,也可以多实现,甚至可以在继承一个类的同时,实现多个接口.
- 接口和接口:继承关系,可以单继承,也可以多继承
抽象类和接口的对比
- 成员变量:
抽象类:可以定义变量,也可以定义常量
接口:只能定义常量
- 成员方法:
抽象类:可以定义具体方法,也可以定义抽象方法
接口:只能定义抽象方法
- 构造方法:
抽象类:有
接口:没有
抽象类:对事物做抽象(描述事物)
接口:对行为抽象(制定规则)
接口的应用场景
接口可以为程序制定规则,使代码更规范
案例解析
/*
案例
需求:请采用面向对象的思想实现木门和电动报警门的案例,并在测试类中进行测试
①木门
成员变量:宽,高,品牌
成员方法:开门,关门
②电动报警门:
成员变量:宽,高,品牌
成员方法:开门,关门,报警
思路:
①定义报警 (Alarm)接口
成员方法:报警
②定义门 (Door)抽象类
成员变量:宽,高,品牌
构造方法:无参,带参
成员方法:get/set方法,开门,关门
③定义木门类(WoodDoor),继承门类
构造方法:无参,带参成员方法:开门,关门
④定义电动报警门类(ElectricAlarmDoor),继承门类,实现报警接口
构造方法:无参,带参
成员方法:开门,关门,报警
⑤定义测试类(InterfaceTest),创建对象进行测试
*/
public class InterfaceTest {
public static void main(String[] args) {
// 测试木门
WoodDoor woodDoor = new WoodDoor();
woodDoor.setBrand("美心");
woodDoor.setWidth(1.2);
woodDoor.setHeight(2.5);
System.out.println(woodDoor.getBrand()+","+woodDoor.getWidth()+","+woodDoor.getHeight());
woodDoor.open();
woodDoor.close();
System.out.println("--------------");
// 测试电动报警门
ElectricAlarmDoor alarmDoor = new ElectricAlarmDoor(2.0,3.1,"木洋");
System.out.println(alarmDoor.getBrand()+","+alarmDoor.getWidth()+","+alarmDoor.getHeight());
alarmDoor.open();
alarmDoor.close();
alarmDoor.alarm();
}
}
// 报警 (Alarm)接口
interface Alarm {
public abstract void alarm();
}
// 定义门 (Door)抽象类
abstract class Door {
// 宽,高,品牌
private double width;
private double height;
private String brand;
public Door() {
}
public Door(double width, double height, String brand) {
this.width = width;
this.height = height;
this.brand = brand;
}
public double getWidth() {
return width;
}
public void setWidth(double width) {
this.width = width;
}
public double getHeight() {
return height;
}
public void setHeight(double height) {
this.height = height;
}
public String getBrand() {
return brand;
}
public void setBrand(String brand) {
this.brand = brand;
}
// 开门,关门
public abstract void open();
public abstract void close();
}
// 定义木门类(WoodDoor)
class WoodDoor extends Door {
public WoodDoor() {
}
public WoodDoor(double width, double height, String brand) {
super(width, height, brand);
}
@Override
public void open() {
System.out.println("木门手动开");
}
@Override
public void close() {
System.out.println("木门手动关");
}
}
// 定义电动报警门类(ElectricAlarmDoor)
class ElectricAlarmDoor extends Door implements Alarm{
public ElectricAlarmDoor() {
}
public ElectricAlarmDoor(double width, double height, String brand) {
super(width, height, brand);
}
@Override
public void open() {
System.out.println(getBrand() + "电动报警门自动开");
}
@Override
public void close() {
System.out.println(getBrand() + "电动报警门自动关");
}
@Override
public void alarm() {
System.out.println(getBrand() + "电动报警门在报警");
}
}
总结:
接口分为狭义和广义的接口;
接口也是一种数据类型,适用于向上转型和向下转型;
接口中所有的方法都是抽象方法,接口中不能定义实例字段;
要明确接口与类、抽象类的区别;
一个类只能继承一个类,但能实现多个接口;
一个接口能继承另外多个接口;
一般情况下,接口中的每个方法都是隐式抽象的;
接口中可以有变量,默认都会成为常量;
JDK 8之前,接口中的方法是没有默认实现的default;(可以有方法体)(实现类调用)
JDK 9开始,接口中允许将方法定义为private;(可以有方法体)
静态方法:使用static修饰,默认public修饰;(可以有方法体)
接口其他注意事项(了解)
- 一个接口继承多个接口,如果多个接口中存在方法签名冲突,则此时不支持多继承。
interface i{
void test();
}
interface j{
String test();
}
//i接口中test方法无返回值,j接口中test方法有返回值,方法签名冲突
- 一个类实现多个接口,如果多个接口中存在方法签名冲突,则此时不支持多实现。
- 一个类继承了父类,又同时实现了接口,父类中和接口中有同名的默认方法,实现类会优先用父类的。
- 一个类实现了多个接口,多个接口中存在同名的默认方法,可以不冲突,这个类重写该方法即可。