接口是java中的核心概念之一。Java Interface 是Java 编程语言的核心部分,不仅在JDK 中而且在Java 设计模式中都被大量使用。大多数框架都大量使用 java 接口。
Java中的接口
Java中的接口提供了一种实现抽象的方法。Java 接口也用于定义子类要实现的契约。
例如,假设我们要创建一个由多个形状组成的绘图。在这里我们可以创建一个接口Shape
并定义不同类型的 Shape 对象将实现的所有方法。为简单起见,我们只能保留两种方法——draw()
绘制形状和getArea()
返回形状的面积。
Java 接口示例
基于上述要求,我们的 Shape 界面将如下所示。
例如,假设我们要创建一个由多个形状组成的绘图。在这里我们可以创建一个接口Shape
并定义不同类型的 Shape 对象将实现的所有方法。为简单起见,我们只能保留两种方法——draw()
绘制形状和getArea()
返回形状的面积。
Java 接口示例
基于上述要求,我们的 Shape 界面将如下所示。
Shape.java
package com.journaldev.design;
public interface Shape {
//implicitly public, static and final
public String LABLE="Shape";
//interface methods are implicitly abstract and public
void draw();
double getArea();
}
关于 Java 接口的要点
-
interface
是用于在java中创建接口的代码。 -
我们不能在 java 中实例化一个接口。
-
接口提供了绝对的抽象,但是抽象类可以有方法实现而接口不能。
-
接口不能有构造函数,因为我们不能实例化它们,接口不能有带有主体的方法。
-
默认情况下,接口的任何属性都是public、static和final,所以我们不需要为属性提供访问修饰符,但如果我们这样做,编译器也不会抱怨它。
-
默认情况下,接口方法是隐式抽象和公共的,这是完全有意义的,因为方法没有主体,因此子类可以提供方法实现。
-
一个接口不能扩展任何类,但它可以扩展另一个接口。
public interface Shape extends Cloneable{}
是一个接口扩展另一个接口的例子。其实java在接口中提供了多重继承,意思是一个接口可以扩展多个接口。 -
implements
类使用关键字来实现接口。 -
实现接口的类必须为其所有方法提供实现,除非它是抽象类。例如,我们可以像这样在抽象类中实现上述接口:
ShapeAbs.java
package com.journaldev.design; public abstract class ShapeAbs implements Shape { @Override public double getArea() { // TODO Auto-generated method stub return 0; } }
-
我们应该始终尝试根据接口而不是实现来编写程序,以便我们事先知道实现类将始终提供实现,并且将来如果出现更好的实现,我们可以轻松切换到接口。
Java 接口实现示例
现在让我们看看我们的 Shape 接口在 java 中的一些实现。
Circle.java
package com.journaldev.design;
public class Circle implements Shape {
private double radius;
public Circle(double r){
this.radius = r;
}
@Override
public void draw() {
System.out.println("Drawing Circle");
}
@Override
public double getArea(){
return Math.PI*this.radius*this.radius;
}
public double getRadius(){
return this.radius;
}
}
请注意,Circle 类已经实现了接口中定义的所有方法,并且它也有一些自己的方法,例如getRadius()
. 接口实现可以有多种类型的构造函数。让我们看看 Shape 接口的另一个接口实现。
Rectangle.java
package com.journaldev.design;
public class Rectangle implements Shape {
private double width;
private double height;
public Rectangle(double w, double h){
this.width=w;
this.height=h;
}
@Override
public void draw() {
System.out.println("Drawing Rectangle");
}
@Override
public double getArea() {
return this.height*this.width;
}
}
注意覆盖注解的使用,
这是一个测试程序,展示了如何根据接口而不是实现进行编码。
ShapeTest.java
package com.journaldev.design;
public class ShapeTest {
public static void main(String[] args) {
//programming for interfaces not implementation
Shape shape = new Circle(10);
shape.draw();
System.out.println("Area="+shape.getArea());
//switching from one implementation to another easily
shape=new Rectangle(10,10);
shape.draw();
System.out.println("Area="+shape.getArea());
}
}
上述java接口示例程序的输出为:
Drawing Circle
Area=314.1592653589793
Drawing Rectangle
Area=100.0
Java 接口的好处
- 接口为所有的实现类提供了一个契约,所以在接口方面编码是好的,因为实现类不能删除我们正在使用的方法。
- 接口是在我们的代码中定义类型和创建顶级层次结构的起点。
- 由于一个java类可以实现多个接口,所以在大多数情况下最好使用接口作为超类。
Java 接口的缺点
虽然接口提供了很多优点,但它也有一些缺点。
-
我们在设计我们的项目时需要非常谨慎地选择接口方法,因为我们不能在以后的时间点从接口中添加或删除任何方法,这将导致所有实现类的编译错误。有时这会导致在我们的代码中有很多扩展基本接口的接口,这些接口变得难以维护。
-
如果实现类有自己的方法,我们就不能直接在我们的代码中使用它们,因为 Object 的类型是一个没有这些方法的接口。例如,在上面的代码中,我们会得到 code 的编译错误
shape.getRadius()
为了克服这个问题,我们可以使用
类型转换
并使用如下方法:
Circle c = (Circle) shape; c.getRadius();
尽管类类型转换有其自身的缺点。
这就是我在java中的接口所拥有的全部内容。由于我们经常使用java接口,我们应该了解它的特性。确保在设计系统时使用接口,并作为客户端和实现接口的子类之间的契约。