1、什么是接口
接口可以看做是一个“纯”抽象类,它只提供一种形式,并不提供实现。
接口中可以规定方法的原型:方法名、参数列表以及返回类型,但不规定方法主体;也可以包含基本数据类型的数据成员,但它们都默认为static
和final
。
2、接口的作用
- 是面向对象的一个重要机制
- 是继承多个设计
- 建立了类和类之间的“协议”:
- 将类根据其实现的功能分组用接口代表,而不必顾虑它所在的类继承层次;这样可以最大限度地利用动态绑定,隐藏实现细节
- 实现不同类之间的常量共享
- 接口允许我们在看起来不相干的对象之间定义共同行为,如下UML类图所示:
3、接口的语法
[接口修饰符] interface 接口名称 [extends 父接口名]{ //方法的原型声明或静态常量 }
注意:
- 接口的数据成员一定要有初值,且此值将不能再更改,可以省略
final
关键字,即接口中每一个方法是隐式抽象的,接口中的方***被隐式的指定为public abstract
(只能是public abstract
,其他修饰符都会报错); - 接口中的方法必须是抽象方法,不能有方法体,可以省略
public
及abstract
关键字,即接口中的变量会被隐式的指定为public static final
变量(并且只能是public
,用private
修饰会报编译错误)。
4、接口与类的区别
- 接口不能用于实例化对象。
- 接口没有构造方法。
- 接口中所有的方法必须是抽象方法,只能由实现接口的类来实现接口中的方法。
- 接口不能包含成员变量,除了
static
和final
变量。 - 接口不是被类继承了,而是要被类实现。
- 接口支持多继承。
5、抽象类和接口的区别
抽象类中的方法可以有方法体,就是能实现方法的具体功能,但是接口中的方法不行。
注:JDK 1.8 以后,接口里可以有静态方法和方法体了。
抽象类中的成员变量可以是各种类型的,而接口中的成员变量只能是
public static final
类型的。一个类只能继承一个抽象类,而一个类却可以实现多个接口。
强调:接口有以下特性
- 接口是隐式抽象的,当声明一个接口的时候,不必使用
abstract
关键字。- 接口中每一个方法也是隐式抽象的,声明时同样不需要
abstract
关键字。- 接口中的方法都是公有的。
例:接口声明
声明一个接口Shape2D,包括π和计算面积的方法原型
interface Shape2D { //声明Shape2D接口 final double pi = 3.14; //数据成员一定要初始化 public abstract double area(); //抽象方法 }
在接口的声明中,允许省略一些关键字,也可声明如下
interface Shape2D { double pi = 3.14; double area(); }
6、实现接口
(1) 单一接口的实现
不能用new
运算符直接产生接口对象。
利用接口设计类的过程,称为接口的实现,使用implements
关键字,语法如下:
public class 类名称 implements 接口名称 { //在类体中实现接口的方法 //本类声明的更多变量和方法 }
注意:
- 必须实现接口中的所有方法;
- 来自接口的方法必须声明成
public
。
例:实现接口 Shape2D
class Circle implements Shape2D { double radius; public Circle(double r) { radius = r; } public double area() { return (pi * radius * radius); } } class Rectangle implements Shape2D { int length, width; public Rectangle(int l, int w) { length = l; width = w; } public double area() { return (width * length); } } //测试类 public class InterfaceTester { public static void main(String args[]) { Rectangle rect = new Rectangle(5, 6); System.out.println("Area of rect = " + rect.area()); Circle cir = new Circle(2.0) System.out.println("Area of cir = " + cir.area()); } }
运行结果:
Area of rect = 30.0 Area of cir = 12.56
(2) 多个接口的实现
Java不允许一个类有多个超类
一个类可以实现多个接口,通过这种机制可实现对设计的多重继承。
实现多个接口的语法如下:
[类修饰符] class 类名称 implements 接口1, 接口2, … { //在类体中实现接口的方法 //本类声明的更多变量和方法 }
强调:
- 重写接口中声明的方法时,需要注意以下规则:
- 类在实现接口的方法时,不能抛出强制性异常,只能在接口中,或者继承接口的抽象类中抛出该强制性异常。
- 类在重写方法时要保持一致的方法名,并且应该保持相同或者相兼容的返回值类型。
- 如果实现接口的类是抽象类,那么就没必要实现该接口的方法。
- 在实现接口的时候,也要注意一些规则:
- 一个类只能继承一个类,但是能实现多个接口。
- 一个接口能继承另一个接口,这和类之间的继承比较相似。
7、接口类型的引用变量
接口的灵活性就在于“规定了一个类必须做什么,而不管你如何做”。
我们可以定义一个接口类型的引用变量来引用实现接口的类的对象,当这个引用来调用方法时,它会根据实际引用的类的实例来判断具体调用哪个方法(实现了方法在运行时的动态绑定)。
例:
public class VariableTester { public static void main(String args[]) { Shape2D var1, var2; var1 = new Rectangle(5, 6); System.out.println("Area of var1 = " + var1.area()); var2 = new Circle(2.0); System.out.println("Area of var2 = " + var2.area()); } }
运行结果:
Area of rect = 30.0 Area of cir = 12.56
8、接口的扩展
接口可通过扩展的技术派生出新的接口
- 原来的接口称为超接口(super interface);
- 派生出的接口称为子接口(sub interface)。
一个接口能继承另一个接口,和类之间的继承方式比较相似。接口的继承使用extends
关键字,子接口继承父接口的方法。
在Java中,类的多继承是不合法,但接口允许多继承。
在接口的多继承中extends
关键字只需要使用一次,在其后跟着继承接口。
接口扩展的语法:
interface 子接口的名称 extends 超口的名称1, 超接口的名称2, … { //…… }
注意:实现一个接口的类也必须实现其超接口。
例:Shape 是超接口,Shape2D 与 Shape3D 是其子接口。Circle 类及 Rectangle 类实现接口 Shape2D, 而 Box 类及 Sphere 类实现接口 Shape3D。关系可由如下UML类图表示:
代码如下:
//接口声明 //声明Shape接口 interface Shape { double pi = 3.14159; void setColor(String str); } //声明Shape2D接口扩展了Shape接口 interface Shape2D extends Shape { double area(); } //声明Shape3D接口扩展了Shape接口 interface Shape3D extends Shape { double superficialArea(); double volume(); } //类声明 //Circle类实现了Shape2D接口 class Circle implements Shape2D { double radius; String color; public Circle(double r) { radius = r; color = "white"; System.out.println("New Circle: radius = " + radius); } public double area() { return (pi * radius * radius); } public void setColor(String str) { color = str; System.out.println("color = " + color); } } //Rectangle类实现了Shape2D接口 class Rectangle implements Shape2D { int length, width; String color; public Rectangle(int l, int w) { length = l; width = w; color = "white"; System.out.println("New Rectangle: length = " + length + ", width = " + width); } public double area() { return (width * length); } public void setColor(String str) { color = str; System.out.println("color = " + color); } } //Box类实现了Shape3D接口 class Box implements Shape3D { int length, width, height; String color; public Box(int l, int w, int h) { length = l; width = w; height = h; color = "white"; System.out.println("New Rectangle: length = " + length + ", width = " + width + ", height = " + height); } public double superficialArea() { return (2 * length * width + 2 * height * width + 2 * length * height); } public double volume() { return (length * width * height); } public void setColor(String str) { color = str; System.out.println("color = " + color); } } //Sphere类实现了Shape3D接口 class Sphere implements Shape3D { double radius; String color; public Sphere(double r) { radius = r; color = "white"; System.out.println("New Sphere: radius = " + radius); } public double superficialArea() { return (4 * pi * radius * radius); } public double volume() { return (4 * pi * radius * radius * radius / 3); } public void setColor(String str) { color = str; System.out.println("color = " + color); } } //测试类 public class ExtendsInterfaceTester { public static void main(String[] args) { Circle cir; cir = new Circle(2.0); cir.setColor("blue"); System.out.println("Area of Circle cir is " + cir.area()); System.out.println(); Rectangle rec; rec = new Rectangle(5, 6); rec.setColor("red"); System.out.println("Area of Rectangle rec is " + rec.area()); System.out.println(); Box box; box = new Box(3, 4, 5); box.setColor("green"); System.out.println("Superficial Area of Box box is " + box.superficialArea()); System.out.println("Volume of Box box is " + box.volume()); System.out.println(); Sphere sph; sph = new Sphere(15.0); sph.setColor("yellow"); System.out.println("Superficial Area of Sphere sph is " + sph.superficialArea()); System.out.println("Volume of Sphere sph is " + sph.volume()); System.out.println(); } }
运行结果:
New Circle: radius = 2.0 color = blue Area of Circle cir is 12.56636 New Rectangle: length = 5, width = 6 color = red Area of Rectangle rec is 30.0 New Rectangle: length = 3, width = 4, height = 5 color = green Superficial Area of Box box is 94.0 Volume of Box box is 60.0 New Sphere: radius = 15.0 color = yellow Superficial Area of Sphere sph is 2827.431 Volume of Sphere sph is 14137.155
9、标记接口 △
最常用的继承接口是没有包含任何方法的接口。
标记接口是没有任何方法和属性的接口。它仅仅表明它的类属于一个特定的类型,供其他代码来测试允许做一些事情。
标记接口作用:使对象拥有某个或某些特权。(就是给某个对象打个标、盖个戳)
例如:java.awt.event
包中的MouseListener
接口继承的java.util.EventListener
接口定义如下:
package java.util; public interface EventListener {}
标记接口主要用于以下两种目的:
建立一个公共的父接口:
正如
EventListener
接口,这是由几十个其他接口扩展的Java API,你可以使用一个标记接口来建立一组接口的父接口。例如:当一个接口继承了EventListener
接口,Java虚拟机(JVM)就知道该接口将要被用于一个事件的代理方案。向一个类添加数据类型:
这种情况是标记接口最初的目的,实现标记接口的类不需要定义任何接口方法(因为标记接口根本就没有方法),但是该类通过多态性变成一个接口类型。