Java 教程是为 JDK 8 编写的。本页中描述的示例和实践未利用在后续版本中引入的改进。
abstract class (抽象类) 是一个声明为 abstract 的类,它可能包含也可能不包含抽象方法。抽象类无法实例化,但可以进行子类化。
abstract method (抽象方法) 是一个没有实现的情况下声明的方法(没有大括号,后跟分号),如下所示:
abstract void moveTo(double deltaX, double deltaY);
如果一个类包含抽象方法,那么类本身 必须 声明为 abstract,如下所示:
public abstract class GraphicObject {
// declare fields
// declare nonabstract methods
abstract void draw();
}
当抽象类被子类化时,子类通常为其父类中的所有抽象方法提供实现。但是,如果没有,则子类也必须声明为 abstract。
abstract 修饰符不用于接口方法。(可以使用,但不需要。)
抽象类与接口类似。你无法实例化它们,并且它们可能声明一些包含或不包含实现的混合方法。但是,使用抽象类,你可以声明非静态和 final 的字段,并定义 public,protected 和 private 具体方法。使用接口,所有字段都自动为 public,static 和 final,并且你声明或定义的所有方法(作为默认方法)都是 public 的。此外,你只能继承一个类,无论它是否是抽象的,而你可以实现任意数量的接口。
你应该使用抽象类还是接口?
Comparable 和 Cloneable 由许多不相关的类实现。JDK 中抽象类的一个示例是 AbstractMap,它是集合框架的一部分。它的子类(包括 HashMap,TreeMap 和 ConcurrentHashMap)共享许多方法(包括 get,put,isEmpty,containsKey和containsValue),这些方法由 AbstractMap 定义。
JDK 中实现多个接口的类的示例是 HashMap,它实现接口 Serializable,Cloneable ,和 Map<K, V>。通过阅读这个接口列表,你可以推断出 HashMap 的实例(无论实现该类的开发人员或公司)是可以克隆的,是可序列化的(这意味着它可以转换为字节流;请参阅 Serializable Objects 部分),并具有 map 的功能。此外,Map<K, V> 接口已经增强了许多默认方法,例如 merge 和 forEach 已经实现这个接口的旧类不必定义。
请注意,许多软件库都使用抽象类和接口; HashMap 类实现了几个接口,并且还继承了抽象类 AbstractMap。
在面向对象的绘图应用程序中,你可以绘制圆形,矩形,线条,贝塞尔曲线和许多其他图形对象。这些对象都具有某些状态(例如:位置,方向,线条颜色,填充颜色)和行为(例如:moveTo,rotate,resize,draw)。所有图形对象中的一些状态和行为都是相同的(例如:位置,填充颜色和 moveTo)。其他需要不同的实现(例如,调整大小或绘制)。所有 GraphicObject 必须能够自己绘制或调整大小;他们只是在做不同的事情上有所不同。这是抽象超类的完美情况。你可以利用相似性并声明所有图形对象都从相同的抽象父对象继承(例如,GraphicObject),如 下图所示。

Classes Rectangle, Line, Bezier, and Circle Inherit from GraphicObject
首先,声明一个抽象类 GraphicObject,以提供由所有子类完全共享的成员变量和方法,例如当前位置和 moveTo 方法。GraphicObject 还声明方法的抽象方法,例如 draw 或 resize,这些方法需要由所有子类实现,但必须以不同的方式实现。GraphicObject 类看起来像这样:
abstract class GraphicObject {
int x, y;
...
void moveTo(int newX, int newY) {
...
}
abstract void draw();
abstract void resize();
}
GraphicObject 的每个非抽象子类,例如 Circle 和 Rectangle,必须提供 draw 和 resize 方法:
class Circle extends GraphicObject {
void draw() {
...
}
void resize() {
...
}
}
class Rectangle extends GraphicObject {
void draw() {
...
}
void resize() {
...
}
}
在 Interfaces 的部分中,注意到实现接口的类必须实现接口的 所有 方法。但是,如果声明该类声明为 abstract,则可以定义一个不实现所有接口方法的类。例如,
abstract class X implements Y {
// implements all but one method of Y
}
class XX extends X {
// implements the remaining method in Y
}
在这种情况下,类 X 必须是 abstract,因为它没有完全实现 Y,但是类 XX ,实际上,它完全实现 Y。
抽象类可以包含 static 字段和 static 方法。你可以将这些静态成员与类引用一起使用(例如,AbstractClass.staticMethod()),就像使用任何其他类一样。