Java界面编程入门:创建美观的图形用户界面(GUI)应用

这是文章《Java接口》的第1部分(共1部分)。

内容片段: Java中的接口是核心概念之一。Java接口是Java编程语言的核心部分,并且不仅在JDK中使用得很多,在Java设计模式中也被广泛使用。大多数框架都大量使用Java接口。

Java接口

Java的接口提供了一种实现抽象的方式。Java接口还用于定义子类要实现的契约。举个例子,假设我们想要创建一个由多个形状组成的图形。在这里,我们可以创建一个名为Shape的接口,并定义所有不同类型的形状对象将要实现的方法。为了简化,我们可以只保留两个方法 – draw()用于绘制形状和getArea()用于返回形状的面积。

Java接口示例

基于上述要求,我们的Shape接口将如下所示:Shape.java。

package com.Olivia.design;

public interface Shape {

	//隐式地声明为public、static和final
	public String LABLE="Shape";
	
	//接口方法隐式地声明为abstract和public
	void draw();
	
	double getArea();
}

Java接口的重要要点

  1. 接口是用于在Java中创建抽象的代码。
  2. 我们不能在Java中实例化一个接口。
  3. 接口提供了绝对的抽象,上一篇文章中我们学到了在Java中使用抽象类来提供抽象,但是抽象类可以有方法实现,而接口不能。
  4. 接口不能有构造函数,因为我们不能实例化它们,并且接口不能有带有方法体的方法。
  5. 默认情况下,接口的任何属性都是公共的、静态的和最终的,所以我们不需要为属性提供访问修饰符,但如果我们提供,编译器也不会报错。
  6. 默认情况下,接口方法是隐式抽象和公共的,这是有道理的,因为方法没有方法体,子类可以提供方法的实现。
  7. 接口不能扩展任何类,但可以扩展另一个接口。public interface Shape extends Cloneable{}就是一个接口扩展另一个接口的例子。实际上,Java在接口中提供了多重继承,这意味着一个接口可以继承多个接口。
  8. implements关键字由类用于实现一个接口。
  9. 实现接口的类必须提供所有方法的实现,除非它是一个抽象类。例如,我们可以像这样在一个抽象类中实现上述接口:ShapeAbs.java
package com.Olivia.design;

public abstract class ShapeAbs implements Shape {

@Override
public double getArea() {
	// TODO 自动生成的方法存根
	return 0;
}
}

我们应该始终尝试使用接口来编写程序,而不是依赖于具体的实现,这样我们就可以事先知道实现类将始终提供实现,而且如果将来出现了更好的实现,我们可以轻松地切换到该实现。

Java接口实现示例

现在让我们来看看在Java中实现我们的形状接口的一些示例。Circle.java

package com.Olivia.design;

public class Circle implements Shape {

	private double radius;

	public Circle(double r){
		this.radius = r;
	}
	
	@Override
	public void draw() {
		System.out.println("绘制圆形");
	}
	
	@Override
	public double getArea(){
		return Math.PI*this.radius*this.radius;
	}

	public double getRadius(){
		return this.radius;
	}
}

请注意,Circle类已经实现了接口中定义的所有方法,并且它还有一些自己的方法,比如getRadius()。接口实现可以有多种类型的构造函数。让我们再看一个Shape接口的实现,Rectangle.java。

package com.Olivia.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("绘制矩形");
	}

	@Override
	public double getArea() {
		return this.height*this.width;
	}

}

注意使用override注释,了解在Java中的注释以及为什么在覆盖Java方法时应该始终使用override注释。下面是一个测试程序,展示如何根据接口而不是具体实现进行编码。ShapeTest.java

package com.Olivia.design;

public class ShapeTest {

	public static void main(String[] args) {
		
		//面向接口编程而不是面向实现编程
		Shape shape = new Circle(10);
		
		shape.draw();
		System.out.println("面积="+shape.getArea());
		
		//轻松地从一个实现切换到另一个实现
		shape=new Rectangle(10,10);
		shape.draw();
		System.out.println("面积="+shape.getArea());
	}

}

以上Java接口示例程序的输出是:

绘制圆形
面积=314.1592653589793
绘制矩形
面积=100.0

Java接口的好处

  1. 接口为所有实现类提供了一个合同,因此以接口编程是好的,因为实现类无法删除我们正在使用的方法。
  2. 接口对于定义类型和创建代码中的顶级层次结构是很好的起点。
  3. 由于Java类可以实现多个接口,在大多数情况下最好将接口用作超类。

Java接口的缺点

虽然接口提供了许多优势,但也有一些缺点。

  1. 在设计我们的项目时,我们需要非常谨慎地选择接口方法,因为我们无法在以后的时间点中添加或删除接口方法,否则会导致所有实现类的编译错误。有时候,这会导致我们的代码中有很多扩展基本接口的接口,这变得很难维护。
  2. 如果实现类有自己的方法,我们无法直接在我们的代码中使用它们,因为对象的类型是一个没有这些方法的接口。例如,上面的代码中,我们将得到代码shape.getRadius()的编译错误。为了解决这个问题,我们可以使用类型转换并像这样使用方法:
Circle c = (Circle) shape;
c.getRadius();

虽然类的类型转换也有其缺点。

这就是我在Java中提供的接口。因为我们经常使用Java接口,所以我们应该了解它的特点。确保在设计系统时使用接口,并将其作为客户端和实现接口的子类之间的合约。更新:Java 8使用默认方法和静态方法实现改变了接口的定义。欲了解更多详情,请阅读Java 8接口。

bannerAds