Java 教程是为 JDK 8 编写的。本页中描述的示例和实践未利用在后续版本中引入的改进。
在前面的课程中,你已经多次看到 inheritance (继承)。在 Java 语言中,类可以从其他类 derived (派生),从而从那些类 inheriting (继承) 字段和方法。
Object
,它没有超类,每个类有且只有一个直接超类(单继承)。在没有任何其他显式超类的情况下,每个类都隐式地是 Object
的子类。Object
。这样的类被称为 descended (继承了) (译注:可以理解为后代,意会一下)继承链中的所有类延伸回 Object
。
继承的想法很简单但很强大:当你想创建一个新类并且已经有一个包含你想要的代码的类时,你可以从现有的类派生你的新类。在这样做时,你可以重用现有类的字段和方法,而无需自己编写(和调试!)它们。
子类从其超类继承所有 members (成员)(字段,方法和嵌套类)。构造函数不是成员,因此它们不能由子类继承的,但是可以从子类调用超类的构造函数。
在 java.lang
包中定义的 Object
类定义并实现所有类共有的行为,包括你编写的类。在 Java 平台中,许多类直接从 Object
派生,其他类派生自其中一些类,依此类推,形成类的层次结构。
Java 平台中的所有类都是 Object 的后代
在层次结构的顶部,Object
是所有类中最一般的。层次结构底部附近的类提供更专业的行为。
以下是在“类和对象”类中提供的 Bicycle
类的可能实现的示例代码:
public class Bicycle { // the Bicycle class has three fields public int cadence; public int gear; public int speed; // the Bicycle class has one constructor public Bicycle(int startCadence, int startSpeed, int startGear) { gear = startGear; cadence = startCadence; speed = startSpeed; } // the Bicycle class has four methods public void setCadence(int newValue) { cadence = newValue; } public void setGear(int newValue) { gear = newValue; } public void applyBrake(int decrement) { speed -= decrement; } public void speedUp(int increment) { speed += increment; } }
MountainBike
类的类声明是 Bicycle
的子类,可能如下所示:
public class MountainBike extends Bicycle { // the MountainBike subclass adds one field public int seatHeight; // the MountainBike subclass has one constructor public MountainBike(int startHeight, int startCadence, int startSpeed, int startGear) { super(startCadence, startSpeed, startGear); seatHeight = startHeight; } // the MountainBike subclass adds one method public void setHeight(int newValue) { seatHeight = newValue; } }
MountainBike
继承 Bicycle
的所有字段和方法,并添加字段 seatHeight
以及设置它的方法。除了构造函数之外,就好像你已经从头开始编写了一个新的 MountainBike
类,有四个字段和五个方法。但是,你不必完成所有工作。如果 Bicycle
类中的方法很复杂并且需要花费大量时间来调试,这将特别有价值。
无论子类所在的包是什么,子类都会继承其父类的所有 public 和 protected 成员。如果子类与其父类在同一个包中,它还会继承父类的 package-private 成员。你可以按原样使用继承的成员,替换它们,隐藏它们或用新成员补充它们:
super
来调用超类的构造函数。本课程的以下部分将扩展这些主题。
子类不继承其父类的 private
成员。但是,如果超类具有访问其 private 字段的 public 或 protected 方法,则子类也可以使用这些方法。
嵌套类可以访问其封闭类的所有 private 成员 - 包括字段和方法。因此,子类继承的 public 或 protected 嵌套类可以间接访问超类的所有 private 成员。
我们已经看到一个对象是实例化它的类的数据类型。例如,如果我们写
public MountainBike myBike = new MountainBike();
那么 myBike
的类型为 MountainBike
。
MountainBike
来自 Bicycle
和 Object
。因此,MountainBike
是 Bicycle
并且也是 Object
,它可以在任何调用 Bicycle
或 Object
的地方使用。
反过来不一定正确:Bicycle
可能是 一个 MountainBike
,但不一定如此。类似地,Object
可能是 一个 Bicycle
或 MountainBike
,但不一定如此。
Casting (转换) 显示在继承和实现允许的对象中使用一种类型的对象代替另一种类型。例如,如果我们写
Object obj = new MountainBike();
然后 obj
既是 Object
又是 MountainBike
(直到 obj
分配另一个 不是 MountainBike
的对象)。这称为 implicit casting (隐式转换)。
另一方面,如果我们写
MountainBike myBike = obj;
我们会得到编译时错误,因为编译器不知道 obj
是 MountainBike
。但是,我们可以 告诉 编译器我们承诺分配一个 MountainBike
给 obj
,通过 explicit casting (显示转换):
MountainBike myBike = (MountainBike)obj;
此强制转换插入运行时检查 obj
被分配了一个 MountainBike
,以便编译器可以安全地假设 obj
是 MountainBike
。如果 obj
在运行时不是 MountainBike
,则会抛出异常。
instanceof
运算符对特定对象的类型进行逻辑测试。这可以避免由于不正确的强制转换而出现运行时错误。例如:
if (obj instanceof MountainBike) { MountainBike myBike = (MountainBike)obj; }
这里 instanceof
运算符验证 obj
是否引用 MountainBike
,以便我们可以使用转换,而不会抛出运行时异常。