Java 中的接口
Java 中的接口是核心概念之一。Java 接口是 Java 编程语言的核心部分,不仅在 JDK 中被广泛使用,而且在Java 设计模式中也被广泛使用。大多数框架都大量使用 Java 接口。
Java中的接口
Java 中的接口提供了一种实现抽象的方法。Java 接口也用于定义子类要实现的契约。例如,假设我们要创建一个由多个形状组成的图形。在这里,我们可以创建一个接口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 中实例化接口。
-
接口提供绝对的抽象,在上一篇文章中,我们了解了Java 中的抽象类以提供抽象,但抽象类可以有方法实现,而接口不能。
-
接口不能有构造函数,因为我们不能实例化它们,并且接口不能有带有主体的方法。
-
默认情况下,接口的任何属性都是公共的、静态的和最终的,所以我们不需要为属性提供访问修饰符,但如果我们这样做了,编译器也不会对此抱怨。
-
默认情况下,接口方法是隐式抽象和公共的,这是完全有意义的,因为该方法没有主体,因此子类可以提供方法实现。
-
接口不能扩展任何类,但可以扩展另一个接口。
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接口实现示例
现在让我们看看 Java 中 Shape 接口的一些实现。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;
}
}
注意使用 override 注释,了解Java 中的注释以及为什么在重写 Java 中的方法时应始终使用 override 注释。这是一个测试程序,展示了如何根据接口而不是实现进行编码。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 接口,因此我们应该了解其功能。确保在设计系统时使用接口,并将其作为客户端与实现接口的子类之间的契约。更新:Java 8 通过引入默认方法和静态方法实现改变了接口的定义。有关更多详细信息,请阅读Java 8 接口。