一、接口的概述
什么时候用接口:当抽象类中的方法都是抽象方法的时候,该抽象类可以用另外一种形式来定义和表示,那就是接口interface。
接口概述:接口和数组、类、抽象类是同一个层次的概念。
为什么要有接口:接口就是比“抽象类”还“抽象”的“抽象类”,可以更加规范的对子类进行约束。全面地专业地实现了:规范和具体实现的分离。
二、接口的定义
定义接口的关键字:interface
【示例】接口的定义
interface 接口名 [extends 父接口1, 父接口2, …] { // 常量定义 // 方法定义 } |
定义接口所在的仍为.java 文件(虽然声明时使用的为interface 关键字的编译后仍然会产生.class 文件)。
接口可以看做是一种只包含了功能声明的特殊类。
注意:使用extends可实现接口的多继承!接口不能实例化!
接口的组成:
接口中定义的属性:都属于全局静态常量,默认由public static final 来修饰。
接口中定义的方法:在JDK1.8以前,都属于抽象方法,默认由public abstract来修饰, 在JDK1.8以后,接口中还可以包含普通的静态方法和default修饰的成员方法。
【示例】接口的组成
public interface Flyable { // 属性:默认为全局静态属性 /public static final/ double MAX_HEIGHT = 8000; // 方法:JDK1.8以前默认为抽象方法 /public abstract/ void fly(); // JDK1.8之后还可以包含静态方法和default修饰的成员方法 public static void showInfo1() {} default void showInfo2() {} } |
注意:接口中不能有构造方法,因为接口中没有需要初始化的成员变量。
三、接口的实现
类与类的继承:extends。类与接口的继承:implements。
接口实现格式:
class 实现类 [extends 父类] implements 接口 { // 重写接口中的方法 } |
在类实现接口后,该类就会将接口中的抽象方法继承过来,此时该类需要重写该抽象方法,完成具体的逻辑。
【示例】接口的实现
// 接口 interface Flyable { // 建议不要省略,以提高阅读性 /public abstract/ void fly(); } // 实现类 class Bird implements Flyable{ public void fly() { System.out.println("鸟儿在天空自由的飞翔"); } } // 测试类 public class Test { public static void main(String[] args) { Bird bird = new Bird(); bird.fly(); } } |
注意事项:
1)如果子类实现了接口的所有抽象方法,那么该子类可以实例化
2)如果子类只实现了接口的部分抽象方法,那么子类就是一个抽象类,不能被实例化!
四、接口的多实现
了解了接口的特点后,那么想想为什么要定义接口,使用抽象类描述也没有问题,接口到底有啥用呢?接口完全支持多实现,和类的继承类似,实现类可以实现多个接口,将会获得接口中所定义的一切。
在java中,一个类只能继承一个类,但同时可以实现多个接口,既可以实现多重继承的效果和功能,也避免的多重继承的危险性。
【示例】接口多实现案例
// 父类 class Person { String name; public void eat() {} } // 接口 interface Runner { public abstract void run(); } interface Flyer { public abstract void fly(); } // Student类,既继承Person类,又实现Runner和Flyer接口 class Student extends Person implements Runner, Flyer { @Override public void fly() { System.out.println("Student fly方法"); } @Override public void run() { System.out.println("Student run方法"); } } |
五、接口和抽象类的区别
接口是对动作的抽象,抽象类是对根源的抽象。
抽象级别(从高到低):接口 > 抽象类 > 普通类。
接口:人可以吃东西,狗也可以吃东西,我们可以把“吃东西”定义成一个接口,然后让这些类去实现它。
抽象类:人有姓名和年龄属性,也有吃饭的行为,狗也有姓名和年龄属性,也有吃饭行为,我们可以把“相同的属性和行为”定义在一个抽象类中,然后让这些类去继承这个抽象类。
相同点:
- 都是不断向上抽取而来的,都不能被实例化。
- 都包含抽象方法,但不提供具体的实现。
不同点:
1)抽象类需要被继承extends,而且只能单继承;
接口需要被实现implements,而且可以多实现。
2)抽象类中可以定义成员变量也可以定义静态变量;
接口中定义的变量,默认为全局静态常量(public static final来修饰)。
3)抽象类中可以定义构造方法,方便子类调用并给抽象类中的成员变量赋值;
接口中不能定义构造方法,因为接口中没有成员变量需要初始化!
4)抽象类中可以定义普通方法,也可定义抽象方法(abstrct);
接口JDK1.8之前,只能定义抽象方法(public abstrct),JDK1.8之后还可以定义静态方法。
5)抽象类的继承,描述的“is a”关系,用于定义该体系的基本共性内容;
接口的实现,描述的“is like a”关系,用于定义体系之外的额外行为。